metaclass & __slots__
Jonathan Hogg
jonathan at onegoodidea.com
Thu Jul 4 03:21:16 EDT 2002
On 3/7/2002 22:17, in article
c2595393.0207031317.7d9bb013 at posting.google.com, "Holden Caulfield"
<phoebe_1 at att.net> wrote:
> It looks like because the Metalcass statement is executed in the end
> of the class statement, hence the class methods seems to have a
> "early" binding to the __slots__ variable. Is this behaviour normal?
The __slots__ stuff works at allocation rather than initialisation (along
with lots of other magic). So you need to override __new__ instead of
__init__ in your metaclass.
I made the following changes to your code:
-----
class MX(type):
def __new__(cls,name,bases,dict):
props = {}
slots = dict.get('__slots__', [])
print slots
for v in dict.keys():
vs = v.startswith
if vs("_get_") or vs("_set_"):
props[v[5:]] = 1
for v in props.keys():
fget = dict.get("_get_%s" % v, None)
fset = dict.get("_set_%s" % v, None)
dict[v] = property(fget,fset)
slots.append("_%s__%s" % (name,v))
dict['__slots__'] = slots
return super(MX, cls).__new__(cls,name,bases,dict)
class X(object):
__metaclass__ = MX
__slots__ = ['z']
def __init__(self):
self.x = 1
self.z = 2
def _get_x(self):
return self.__x
def _set_x(self,v):
self.__x = v
def Test():
y = X()
y.x = 4
print y.x
if __name__ == "__main__": Test()
-----
which gives me the desired result. Note that you do all your work on the
dict in __new__ as the class hasn't been created yet (the 'cls' in the
__new__ method is 'MX'), then you chain the type.__new__ to do the actual
class creation.
Jonathan
More information about the Python-list
mailing list