Is a Borg rebellion possible? (a metaclass question)
Steven Bethard
steven.bethard at gmail.com
Fri Sep 7 16:54:15 EDT 2007
Carsten Haese wrote:
> Indeed, if you have an __init__ method that shouldn't see the "group"
> argument, you need a metaclass after all so you can yank the "group"
> argument between __new__ and __init__. The following code seems to work,
> but it's making my brain hurt:
>
> class SplinterBorgMeta(type):
> def __call__(cls, *args, **kwargs):
> inst = cls.__new__(cls, *args, **kwargs)
> kwargs.pop("group",None)
> inst.__init__(*args,**kwargs)
> return inst
>
> class SplinterBorg(object):
> __metaclass__ = SplinterBorgMeta
> _shared_states = {}
> def __new__(cls, *a, **k):
> group = k.pop("group","BORG")
> obj = object.__new__(cls, *a, **k)
> obj.__dict__ = cls._shared_states.setdefault(group,{})
> return obj
>
> class MyClass(SplinterBorg):
> def __init__(self, name):
> self.name = name
>
I think I would probably write that as::
>>> class SplinterBorgMeta(type):
... def __init__(cls, name, bases, bodydict):
... cls._shared_states = {}
... def __call__(cls, *args, **kwargs):
... group = kwargs.pop('group', None)
... inst = cls.__new__(cls, *args, **kwargs)
... inst.__dict__ = cls._shared_states.setdefault(group, {})
... inst.__init__(*args, **kwargs)
... return inst
...
>>> class MyClass(object):
... __metaclass__ = SplinterBorgMeta
... def __init__(self, name):
... self.name = name
...
>>> a = MyClass('a')
>>> aa = MyClass('aa')
>>> b = MyClass('b', group='b')
>>> bb = MyClass('bb', group='b')
>>> a.name, aa.name, b.name, bb.name
('aa', 'aa', 'bb', 'bb')
That is, I don't think there's really a need for __new__ if you're using
a metaclass. Just set the instance's __dict__ in the __call__ method of
the metaclass.
STeVe
More information about the Python-list
mailing list