Proper class initialization

Steven Bethard steven.bethard at gmail.com
Thu Mar 2 13:14:09 EST 2006


Kent Johnson wrote:
> Steven Bethard wrote:
>> I don't run into this often, but when I do, I usually go Jack 
>> Diederich's route::
>>
>>     class A(object):
>>         class __metaclass__(type):
>>             def __init__(cls, name, bases, classdict):
>>                 cls.sum = sum(xrange(10))
> 
> I think you should call the superclass __init__ as well:
> 
>     class __metaclass__(type):
>         def __init__(cls, name, bases, classdict):
>             super(__metaclass__, cls).__init__(name, bases, classdict)
>             cls.sum = sum(xrange(10))

Yes, thanks for the catch.

I'd like to use super there, but I think you'll find that it doesn't 
work because of the order in which A and __metaclass__ get created:

 >>> class A(object):
...     class __metaclass__(type):
...         def __init__(cls, name, bases, cdict):
...             super(__metaclass__, cls).__init__(name, bases, cdict)
...             cls.sum = sum(xrange(10))
...
Traceback (most recent call last):
   File "<interactive input>", line 1, in ?
   File "<interactive input>", line 4, in __init__
NameError: global name '__metaclass__' is not defined


 >>> class A(object):
...     class __metaclass__(type):
...         def __init__(cls, name, bases, classdict):
...             super(A.__metaclass__, cls).__init__(name, bases, classdict)
...             cls.sum = sum(xrange(10))
...
Traceback (most recent call last):
   File "<interactive input>", line 1, in ?
   File "<interactive input>", line 4, in __init__
NameError: global name 'A' is not defined


I played around with a few solutions to this problem, but it seems like 
the cleanest one is just to avoid super:

 >>> class A(object):
...     class __metaclass__(type):
...         def __init__(cls, name, bases, cldict):
...             type.__init__(cls, name, bases, cldict)
...             cls.sum = sum(xrange(10))
...

Of course, this means you can't use some sorts of multiple inheritance 
with A.__metaclass__...

STeVe

P.S.  Here's the best way I found that still uses super:

 >>> class A(object):
...     class __metaclass__(type):
...         def __init__(cls, name, bases, cldict):
...             try:
...                 meta = A.__metaclass__
...             except NameError:
...                 meta = cldict['__metaclass__']
...             super(meta, cls).__init__(name, bases, cldict)
...             cls.sum = sum(xrange(10))
...



More information about the Python-list mailing list