Custom Search

Sunday, December 12, 2010

Metaclasses are used to implement Python class objects

Metaclasses are used to implement Python class objects

Because metaclasses implement classes they are normally used to customise the creation (initialisation) of classes.

Class objects are created at runtime. The interpreter takes the end of a class statement as
a signal to call the appropriate metaclass to create the class-object.

If a class is a new style class (inherits from object) the default metaclass is type.
For old style classes the default metaclass is types.ClassType.


To create the class, the metaclass is called with the following arguments :

type(name, bases, dict)

* 'name': The name of the class
* 'bases': A tuple of the base classes of the class
* 'dict': A dictionary of the attributes of the class

This returns the new class.

The following are basically equivalent :

----------------------------a

def __init__(self, x):
self.x = x

def printX(self):
print self.x

Test = type('Test', (object,), {'__init__': __init__, 'printX': printX})


---------------------------b


class Test(object):
def __init__(self, x):
self.x = x

def printX(self):
print self.x



The Most Basic Example:
***********************

So we can create a very simple metaclass which does nothing.

class PointlessMetaClass(type):
def __new__(meta, classname, bases, classDict):
return type.__new__(meta, classname, bases, classDict)

Rather than calling type directly, our metaclass inherits from type, so it calls
type.__new__(meta...). This means that the metaclass returned is an instance of our class.


Using Metaclasses
*****************

You can set the metaclass for a class by setting its __metaclass__ attribute.

We'll adapt the example for above so that we can see what's going on.

class MetaClass(type):
def __new__(meta, classname, bases, classDict):
print 'Class Name:', classname
print 'Bases:', bases
print 'Class Attributes', classDict
return type.__new__(meta, classname, bases, classDict)

class Test(object):
__metaclass__ = MetaClass
def __init__(self):
pass
def method(self):
pass
classAttribute = 'Something'

If you run this you will see something like :

OUTPUT
======

Class Name: Test
Bases: (<type 'object'>,)
Class Attributes {'__module__': '__main__',
'__metaclass__': <class '__main__.MetaClass'>,
'method': <function method at 0x00B412B0>,
'__init__': <function __init__ at 0x00B41070>,
'classAttribute': 'Something'}

* methods on the class are passed into the metaclass as functions.

You can also set the metaclass at the module level. If you set the variable
__metaclass__ in a module, it will be used for all following class definitions that
don't have an explicit metaclasses. New style classes inherit their metaclasses from object,
so that means all old style classes. So you can do things like make all classes into new
style classes by setting __metaclass__ = type.


Metaclasses are used to implement Python class objects (not instance of a class)
********************************************************************************

class Meta(type):
def __str__(self):
return "Klass"

class A(object):
__metaclass__ = Meta

def __str__(self):
return "instance"

print A
print A()

OUTPUT
======

Klass
instance

Good Example, of metaclass implementation is Django models.
http://code.djangoproject.com/browser/django/trunk/django/db/models/base.py

http://www.voidspace.org.uk/python/articles/metaclasses.shtml

===============================

No comments:

Post a Comment