metaclass & __slots__

Jonathan Hogg jonathan at onegoodidea.com
Thu Jul 4 17:40:44 EDT 2002


On 4/7/2002 17:47, in article
mailman.1025801286.31332.python-list at python.org, "Alex Martelli"
<aleax at aleax.it> wrote:

> More generally, in your __init__ (whether of a metaclass or
> any other class): call the superclass's __init__ AFTER you have
> performed modifications to the arguments, if you need to change
> the arguments and the superclass's __init__ is going to take
> some action based on them.  Metaclasses are no different (in
> this or most other respects) from any other class.

Unfortunately, you can't set or modify __slots__ in the __init__ method of a
metaclass. The damage has already been done by the time you get to the
__init__ method:

>>> class foo( type ):
...     def __init__( cls, name, bases, dict ):
...         dict['__slots__'] = ['x','y']
...         super(foo,cls).__init__( name, bases, dict )
... 
>>> class bar:
...     __metaclass__ = foo
... 
>>> b = bar()
>>> b.x = 10
>>> b.foo = 'heck'
>>> b.__dict__
{'x': 10, 'foo': 'heck'}
>>> 

You need to make the change in the __new__ method before the class is
allocated:

>>> class foo( type ):
...     def __new__( cls, name, bases, dict ):
...         dict['__slots__'] = ['x','y']
...         return type.__new__( cls, name, bases, dict )
... 
>>> class bar:
...     __metaclass__ = foo
... 
>>> b = bar()
>>> b.x = 10
>>> b.foo = 'heck'
Traceback (most recent call last):
  File "<stdin>", line 1, in ?
AttributeError: 'bar' object has no attribute 'foo'
>>> b.__dict__
Traceback (most recent call last):
  File "<stdin>", line 1, in ?
AttributeError: 'bar' object has no attribute '__dict__'
>>> 

See my other post for more on this.

Jonathan




More information about the Python-list mailing list