Is a Borg rebellion possible? (a metaclass question)
André
andre.roberge at gmail.com
Fri Sep 7 15:13:41 EDT 2007
On Sep 7, 3:53 pm, Steve Holden <st... at holdenweb.com> wrote:
> 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:
Because this is what I need to do currently with using the standard
Borg class, and is something I would like to be able to do. Here's a
simplified version of the current usage I have
=====
class Borg(object):
_shared_state = {}
def __new__(cls, *a, **k):
obj = object.__new__(cls, *a, **k)
obj.__dict__ = cls._shared_state
return obj
class BorgConsole(Borg, SingleConsole):
'''Every BorgConsole share a common state'''
def __init__(self, locals={}, filename="Crunchy console"):
SingleConsole.__init__(self, locals, filename=filename)
=====
and it is called via something like
a_console = BorgConsole(locals)
where locals is a previously defined dict. Note that a number of
such instances are created dynamically as the program is used.
What I would like to do is to be able to add a "page_id" (the Borg
group referred to my previous message), so that I could call
a_console = BorgConsole(locals, page_id)
where page_id would be an optional argument, defaulting to the BORG
group, as mentioned in my original post.
I must admit I did not try with keywords arguments ... and will not be
for a couple of hours while I am at work.
>
> 1. It stops the super-class's __init__() method from being called, and
>
I don't understand why this is so here, and not with the usual Borg
case as I used it...
> 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.
>
I do need subclasses (I think) as my classes inherit from more than
the SplinterBorg class... I'll see what I can do following some of
your suggestions.
Thanks for the reply,
André
> 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