Is a Borg rebellion possible? (a metaclass question)

Carsten Haese carsten at uniqsys.com
Fri Sep 7 15:00:10 EDT 2007


On Fri, 2007-09-07 at 15:54 +0000, André wrote:
> Unfortunately, it fails.  Here's what I tried, followed by the
> traceback
> class SplinterBorg(object):
>     _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
>[...]
> Traceback (most recent call last):
>   File "test.py", line 15, in <module>
>     b1 = MyClass('b', group="B")
> TypeError: __init__() got an unexpected keyword argument 'group'

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

The alternatives, as Steve just pointed out, would be not to subclass
SplinterBorg or to provide an __init__ method that expects a "group"
argument.

HTH,

-- 
Carsten Haese
http://informixdb.sourceforge.net





More information about the Python-list mailing list