[lnkForumImage]
TotalShareware - Download Free Software

Confronta i prezzi di migliaia di prodotti.
Asp Forum
 Home | Login | Register | Search 


 

Forums >

comp.lang.python

Re: Choosing a Metaclass?

Steve Holden

2/21/2008 8:02:00 PM

Jeff McNeil wrote:
> Hi list,
>
> Hopefully a quick metaclass question. In the following example, MyMeta
> is a metaclass that does not inherit directly from type:
>
> #!/usr/bin/python
>
> class MyMeta(object):
> def __new__(cls, name, bases, vars):
> print "MyMeta.__new__ called for %s" % name
> return type(name, bases, vars)
>
> class MetaWrapper(object):
> __metaclass__ = MyMeta
>
> class M(MetaWrapper):
> pass
>
> [jeff@marvin ~]$ python t.py
> MyMeta.__new__ called for MetaWrapper
> [jeff@marvin ~]$
>
> When I run that script, it's apparent that although M inherits from
> MetaWrapper, it does not use MyMeta as it's metaclass. However, if I
> change MyMeta to be a subclass of builtin type, it works as I would expect:
>
> [jeff@marvin ~]$ cat t.py
> #!/usr/bin/python
>
> class MyMeta(type):
> def __new__(cls, name, bases, vars):
> print "MyMeta.__new__ called for %s" % name
> return super(MyMeta, cls).__new__(cls, name, bases, vars)
>
> class MetaWrapper(object):
> __metaclass__ = MyMeta
>
> class M(MetaWrapper):
> pass
>
> [jeff@marvin ~]$ python t.py
> MyMeta.__new__ called for MetaWrapper
> MyMeta.__new__ called for M
> [jeff@marvin ~]$
>
> How exactly does Python choose which MC it will use when building a
> class? It doesn't seem to me that the parent class of MyMeta should
> matter in this case?
>
When you create a subclass M of MetaWrapper in your first example,
MetaWrapper is a subclass of object that has no metaclass of its own,
and therefore it resolves __new__() from object:

>>> MetaWrapper.__bases__
(<type 'object'>,)
>>> MetaWrapper.__metaclass__
<class '__main__.MyMeta'>
>>> dir(MyMeta)
['__class__', '__delattr__', '__dict__', '__doc__', '__getattribute__',
'__hash__', '__init__', '__module__', '__new__', '__reduce__',
'__reduce_ex__', '__repr__', '__setattr__', '__str__', '__weakref__']
>>> MetaWrapper.__new__
<built-in method __new__ of type object at 0x6cb92f50>

In your second example MyMeta is a subclass of type, and therefore it
resolves type's __new__(), which is what takes the special actions you
observe when a subclass is defined:

>>> MetaWrapper.__bases__
(<type 'object'>,)
>>> MetaWrapper.__metaclass__
<class '__main__.MyMeta'>
>>> dir(MyMeta)
['__base__', '__bases__', '__basicsize__', '__call__', '__class__',
'__cmp__', '__delattr__', '__dict__', '__dictoffset__', '__doc__',
'__flags__', '__getattribute__', '__hash__', '__init__', '__itemsize__',
'__module__', '__mro__', '__name__', '__new__', '__reduce__',
'__reduce_ex__', '__repr__', '__setattr__', '__str__', '__subclasses__',
'__weakrefoffset__', 'mro']
>>> MetaWrapper.__new__
<built-in method __new__ of type object at 0x6cb92f50>
>>>

Hope this helps. Remember that when there is no __metaclass__ defined in
a class's body (and the module namespace has no default __metaclass__)
the class's metaclass is the type of the class's first base class.

regards
Steve
--
Steve Holden +1 571 484 6266 +1 800 494 3119
Holden Web LLC http://www.hold...