TITLE OF PAPER: Metaclasses, Who, Why, When URL OF PRESENTATION: _URL_of_powerpoint_presentation_ PRESENTED BY: Mike Fletcher REPRESENTING: _name_of_the_company_they_represent_ CONFERENCE: PyCON 2004 DATE: 20040325 LOCATION: _venue_and_room_in_venue_ -------------------------------------------------------------------------- REAL-TIME NOTES / ANNOTATIONS OF THE PAPER: {If you've contributed, add your name, e-mail & URL at the bottom} Let's learn enough about metaclasses to know whether we want to use them. Programming where the clients are programmers Language development Framework development Zope Twisted PEAK/PyProtocols Programming to enable new metaphores/approaches to programming: asspect oriented interface oriented prototype-based Extending the language with a new "types of classes" (a new category of objects) Altering the nature of classes adding functionality (eg: metaclass methods) creating class-like objects (eg: prototypes) which can be instantiated Enforcing constraints as closly as possible Automating complex tasks Meta-programming goals: Goal is to make it natural for a programmer to work in some particular application domain. Domain-specific features should feel built-in and interface well with everything we take for-granted with Python. Create natural programming patterns for end programmers Generally for use within an application domain Programming with the framework should map between Python and domain semantics closely. Allow clients to use standard python programming features fit python semantics as closely as possible (take advantage of python knowledge) make domain specific features feel 'built-in' integrate nicely with generic systems, introspection, pickling, properties Enable declarative approach (arguable) This is a that, not necessarily "register this as a that" This implements that This is persistent This uses that join point Simplify and beautify APIs While doing this, avoid the dangers of "too much magic" The converse of fiting Python sematics closely Going too far can make the system opaque (transparent == good) So we must make sure that it's clear that metaclasses are in use, that there is magic going on. Metaclasses are a tool: there's almost always another way (and used to be, before we had 'em), but they make them more elegant and easy There's little you can't do another way: ex factory objects Basis of Python 2.2+'s type system: standard and reliable Meta-methods and meta-properties (more on those later) you can't do these any other way Use cases (or samples): Class/Interface/Join Point/Aspect registration Allow discovery of classes based on class metadata (of any type) via registration and lookup [Interface Oriented Programming: - Declare interfaces that define particular services - Declare adapters that transform from one interface to another Aspect Oriented Programming: - Define "join points" - functional operations an object may perform - e.g. any time an object sets a particular attribute - Register classes that get invoked on particular join points] Registration summary: automatically register information about an end-programmer's classes at the time the class is created registration is normally fairl benign, it may affect class objectlifetimes, etc Traditional approach: - Define helper function in framework - Require all client classes to call helper function - Possibly provide checking for unregistered uses - Depends on end developer remembering to register the class (and then Bad Things Happening) Class verification: Automated Constrants ensure classes provide all declared interface check for internal coherence of class declaration complain on attempt to subclass a final class complain on overriding of 'final' method Class-format checking, to enforce: coding standards security declarations definition of specified method/properties (e.g. abstract method) Don't go crazy with this More intrusive than mere registration Traditional approach: Require user to call utility function(s) Class construction We want to rewrite a class definition at run-time Modify declared methods, properties or attributes Precondition/postcondition Method wrappers in general Injecting methods (e.g. serialization to database) Renaming Processing human friendly declarative structures (such as security info) into machine-friendly structures Cache or short-circuit class creation Load/create bases/methods/descriptors from system state: Declarative structures in the class defintion Databases or data files Application plug-ins or registered aspects Calculations based on the current state of the moon Load/create bases/methods from non-python definitions data stores or whatever (databases, DTDs, IDL, VRML, anything) even user interaction ("I want that feature, that feature, but not that feature") Summary of class construction use case: Can run arbitrarily complex code at class instantiation remember: too much magic can kill your usability Traditional approach: class factory function from a partially constructed class (mixin): awkward due to creation of two different classes from name/base classes/dictionary: hard to use; no longer looks like a class def plus user still has to remember to do them... (e.g. rebinding class name) Or: directly manipulate the class object mutate class name, dictionary, ... [e.g. Zope security declarations] Use case (final): First-class classes Customized behavior of class objects: attach attributes, methods override base behavior (e.g. __str__) [note that class objects are not normally very active] Class-like objects that also have data Traditional approaches: Store methods/properties outside class Store methods/properties in data classes Create delegate objects that stand in for classes Instances and classes: An instance only knows what its class is through the class interface i.e. it refers to its class -- you can change this A class is just an object that performs this role (implements the class API) interactions normally implimented in interpreter interpreter 'asks' questions about class to answer questiosn about the instance (methods, attributes, isinstance, queries), but generally doens't "ask "the class itself Super-classes: same thing, mostly If a class is just an object that performs the role of a class... ...a metaclass implements that class Classes are largely data (passive) Much of the work done by the interpreter So metaclasses usually focus on class initialization Can think of metaclass as code run at class-definition time that creates a class object instance Metaclasses in Python (finally) Python defines two metaclasses: type() (or types.TypeType) implementation for new-style classes object.__class__ types.ClassType implementation for old-style classes Hooks allow you to specify the metaclass to use for creating the class-object for a given class definition: * call metaclasses directly to create new classes (normally only seen in "constructor" use cases * Class-level __metaclass__ assignment * Module-level __metaclass__ assignment * Inherited from superclass By default, backwards compatable types.ClassType is used Since 'object' is an instance of 'type', subclasses of 'object' inherit the new-style class behavior Metaclasses don't normally affect instances directly - don't affect namespace lookup, MRO, - often run implicitly by import stmts What the class def statement does when you're not looking: class X(Y, z): x = 3 #->here the interpreter calls this: metaclass ('X', (Y, Z), {'x':3, '__module__':'__main__'}) (technical note __call__ == very special. looked up in meta-meta class. There Be Dragons.) This is the only such implicit hook in Python (to date) Function decorators may end up being similar [although more explicit] [As special case of this, '__metaclass__ = type' makes further class defs new-style even if they don't inherit from 'object' explicitly] (see presentation/sample code on site) For mature audiences: the metaclass doesn't have to be a class -- it could be a function that implements the appropriate functionality (e.g. a function that returns a type object (see PyProtocols for example) Metaclass __new__: what to do with it? Modify base classes, class name, dictinoary Cache class definitions Return previously created (class) instances First-class class use cases: metaproperties, metadescriptors, ... [running out of time -- see the paper] Q: You explained how, but not why...? A: That was the first half of the talk -- see the four use cases. Q: But you said you can do all of them different ways; why wouldn't you? A: They're kludgey, error-prone, place too much burden on the end-user (programmer); it often seems cleaner to use metaclasses. -------------------------------------------------------------------------- REFERENCES: {as documents / sites are referenced add them below} Paper: http://www.python.org/pycon/dc2004/papers/24/metaclasses-pycon.pdf [PyProtocols?] -------------------------------------------------------------------------- QUOTES: "Run this class when this class is initialized, and give me back something class like" -------------------------------------------------------------------------- CONTRIBUTORS: {add your name, e-mail address and URL below} Ted Leung, twl@osafoundation.org, http://www.sauria.com/blog Ryan Wilcox, ryanwilcox@mac.com, http://radio.weblogs.com/0100544/ Russell Finn, rsf@sprucehill.com, http://www.sprucehill.com/rsf/blog/ [future] -------------------------------------------------------------------------- E-MAIL BOUNCEBACK: {add your e-mail address separated by commas } -------------------------------------------------------------------------- NOTES ON / KEY TO THIS TEMPLATE: A headline (like a field in a database) will be CAPITALISED This differentiates from the text that follows A variable that you can change will be surrounded by _underscores_ Spaces in variables are also replaced with under_scores This allows people to select the whole variable with a simple double-click A tool-tip is lower case and surrounded by {curly brackets / parentheses} These supply helpful contextual information. -------------------------------------------------------------------------- Copyright shared between all the participants unless otherwise stated...