Need help subclassing Borg

Bengt Richter bokr at oz.net
Sat May 7 15:50:50 EDT 2005


On Sun, 08 May 2005 02:42:09 +1000, Steven D'Aprano <steve at REMOVETHIScyber.com.au> wrote:

>On Sat, 07 May 2005 08:35:21 -0700, wittempj at hotmail.com wrote:
>
>> See mr Martellis comment of 2001/09/06 in mentiond recipe, you then get
>> something like this
>> 
>> -#!/usr/bin/env python
>> -class Borg(object):
>> -    _shared_state = {}
>> -    def __init__(self):
>> -        self.__dict__ = self._shared_state
>> -
>> -class Duck(Borg):
>> -    def __init__(self):
>> -        super(Duck, self).__init__()
>> -        self.__covering = "feathers" # all ducks are feathered
>
>What version of Python are you using? I'm using 2.3.3 and I get this:
>
>py> donald = Duck()
>Traceback (most recent call last):
>  File "<stdin>", line 1, in ?
>  File "<stdin>", line 3, in __init__
>TypeError: super() argument 1 must be type, not classobj
>
>
>
>>-        self.__covering = "feathers" # all ducks are feathered
>>-    def covering(self):
>>-        return self.__covering
>>-
>>-class Rabbit(Borg):
>>-    def __init__(self):
>>-        super(Rabbit, self).__init__()
>>-        self.__covering = "fur" # all rabbits are furry
>> -    def covering(self):
>> -        return self.__covering
>
>Hmmm... I hate to be ungrateful, but apart from being inelegant, it means
>having to write get_attribute() and set_attribute() methods for every
>attribute the caller might conceivably use. I'm sure to miss at least one.
>*wink*
>
>Either that or muck around with __getattr__ and __setattr__, which is
>getting uglier by the minute.
>
>I'm thinking what I might need is a function that generates a Borg-like
>class. So I would do something like:
>
>Rabbit = MakeBorgClass()
># Rabbit is now a class implementing shared state
># all instances of Rabbit share the same state
>Duck = MakeBorgClass()
># Duck is now a class implementing shared state
># all instances of Duck share the same state
># but instances of Duck do not share state with instances of Rabbit
>
>Problem is, I haven't got the foggiest idea how to implement something
>like that. Am I on the right track? Where do I go from here?
>
On to new-style classes perhaps? You could have a base class that automatically
gives a subclass its own _shared_state if it isn't there, and tacks that onto
the new instance. That way you don't have to do it in your subclass inits. E.g.,
(warning, not tested beyond what you see. Just thought of this ;-)

 >>> class Borgomat(object):
 ...     def __new__(cls, *args, **kw):
 ...         if '_shared_state' not in cls.__dict__:
 ...             cls._shared_state = {}
 ...         obj = object.__new__(cls)
 ...         obj.__dict__ = cls._shared_state
 ...         return obj
 ...
 >>> class Duck(Borgomat):
 ...     def __init__(self, **kw):
 ...         self.covering = 'feathers'
 ...         self.__dict__.update(kw)
 ...
 >>> daffy = Duck()
 >>> daffy.covering
 'feathers'
 >>> Duck._shared_state
 {'covering': 'feathers'}
 >>> class Rabbit(Borgomat):
 ...     def __init__(self):
 ...         self.covering = 'fur'
 ...
 >>> bugs = Rabbit()
 >>> bugs.covering
 'fur'
 >>> Rabbit._shared_state
 {'covering': 'fur'}
 >>> bugs.food = 'carrots'
 >>> Rabbit._shared_state
 {'food': 'carrots', 'covering': 'fur'}
 >>> roger = Rabbit()
 >>> roger.food
 'carrots'

Oops, forgot to use the optional keyword arg in Duck ...

 >>> donald = Duck(food='Disney duck chow')
 >>> donald.food
 'Disney duck chow'
 >>> donald.covering
 'feathers'
 >>> daffy.food
 'Disney duck chow'

Some shared state may not be all that appropriate ;-)

Regards,
Bengt Richter



More information about the Python-list mailing list