Is a Borg rebellion possible? (a metaclass question)

Steve Holden steve at holdenweb.com
Fri Sep 7 14:53:54 EDT 2007


André wrote:
> On Sep 7, 10:27 am, Carsten Haese <cars... at uniqsys.com> wrote:
>> On Fri, 2007-09-07 at 12:31 +0000, André wrote:
>>> In my application, I make use of the Borg idiom, invented by Alex
>>> Martelli.
>>> class Borg(object):
>>>     '''Borg Idiom, from the Python Cookbook, 2nd Edition, p:273
>>>     Derive a class form this; all instances of that class will share
>>> the
>>>     same state, provided that they don't override __new__; otherwise,
>>>     remember to use Borg.__new__ within the overriden class.
>>>     '''
>>>     _shared_state = {}
>>>     def __new__(cls, *a, **k):
>>>         obj = object.__new__(cls, *a, **k)
>>>         obj.__dict__ = cls._shared_state
>>>         return obj
>>> ----
>>> This has worked very well so far, but is starting to impose some
>>> unwanted constraints on my program design.
>>> What I would like to do is, to put it figuratively, create a Borg
>>> rebellion with various splinter groups.  In concrete Python terms, I
>>> would like to have
>>> class MyClass(Borg, ...):
>>>    ...
>>> seven_of_nine = MyClass(...)  # part of group "BORG"
>>> two_of_nine = MyClass(...)
>>> splinter1 = MyClass(..., group='splinter')
>>> splinter2 = MyClass(..., group='splinter')
>>> and have splinter 1 and splinter2 share the same state, but a
>>> different state than the one shared by members of the BORG collective.
>>> Any suggestions from the metaclass experts?
>> You don't need a metaclass. Just turn _shared_state into a dictionary of
>> shared states, keyed by the group name:
>>
>> 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
>>
>> HTH,
>>
>> --
>> Carsten Haesehttp://informixdb.sourceforge.net
> 
> 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
> 
> a1 = MyClass('a')
> a2 = MyClass('aa')
> b1 = MyClass('b', group="B")
> 
> 
> 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'
> 
> 
Because your subclass signature is completely wrong. Why did you feel 
you had to add an __init__() method to your subclass? This has two bvad 
effects:

1. It stops the super-class's __init__() method from being called, and

2. It breaks the calling syntax specified in the superclass.

All you really need is to create your SplinterBorgs with appropriate 
group names, you don't neef subclasses at all:

a1 = SplinterBorg(group="one")
a2 = SplinterBorg(group="two")

and so on.

If you want to create subclasses then they should work like this:

class MyBorg1(SplinterBorg):
     def __init__(self):
         SplinterBorg.__init__(self, group='borg1')

and so on, with a different group for each. But this seems over complicated.

regards
  Steve
-- 
Steve Holden        +1 571 484 6266   +1 800 494 3119
Holden Web LLC/Ltd           http://www.holdenweb.com
Skype: holdenweb      http://del.icio.us/steve.holden
--------------- Asciimercial ------------------
Get on the web: Blog, lens and tag the Internet
Many services currently offer free registration
----------- Thank You for Reading -------------




More information about the Python-list mailing list