newbie: class and __dict__ variable.

Terry Reedy tjreedy at udel.edu
Mon Sep 20 20:30:08 CEST 2010


On 9/20/2010 5:51 AM, Bruno Desthuilliers wrote:
> Steven D'Aprano a écrit :
>> On Mon, 20 Sep 2010 09:27:25 +0200, Bruno Desthuilliers wrote:
>>
>>>> If the class has a .__setattr__ method, the first bypasses that method,
>>> It also bypasses object.__setattribute__ and - as a consequence - any
>>> binding descriptor by the same name as the attribute being set.
>>
>> __setattribute__ ?
>>
>>
>>>>> object.__setattribute__
>> Traceback (most recent call last):
>> File "<stdin>", line 1, in <module>
>> AttributeError: type object 'object' has no attribute '__setattribute__'
>>
>
> Duh...
> Brain fart, sorry, shouldn't post before I get my dose of coffee :(
>
> Let's do it again:
>
> Terry Reedy a écrit :
>  > If the class has a .__setattr__ method, the first bypasses that
>  > method,
>
> All new-style classes have a __setattr__ method - whether inherited from
> object or overridden. object.__setattr__ implements the support for
> binding descriptors, so bypassing it will also bypass all binding
> descriptors.
>
> The right way to avoid infinite recursion when overriding __setattr__ is
> to call on the superclass __setattr__, unless of course you *really*
> know what you're doing...

In the 3.x doc, this is now the recommended method. The self.__dict__ 
idiom predates new-style classes, object, and super.

To the OP. It is possible that you have seem bad (useless, redundant) 
uses as well as uses that were necessary with old-style user classes.

> class BarDescriptor(object):
> def __init__(self):
> self.val = None
>
> def __set__(self, instance, value):
> print "stores value elsewhere and trigger some required behaviour"
> self.val = value * 2
>
> def __get__(self, instance, cls=None):
> if instance is None:
> return self
> print "retrieve value from elsewhere and trigger some required behaviour"
> return self.val
>
> # well behaved
> class Foo(object):
> bar = BarDescriptor()
>
> def __init__(self):
> self.bar = 42
>
> def __setattr__(self, name, value):
> print "override __setattr_ for some reason"
> super(Foo, self).__setattr__(name, value)
>
>
> # ugly mess
> class Baaz(Foo):
> bar = BarDescriptor()
>
> def __init__(self):
> self.__dict__['bar'] = 42
>
> def __setattr__(self, name, value):
> print "override __setattr_ for some reason"
> self.__dict__[name] == value
>
>  >>> f = Foo()
> override __setattr_ for some reason
> stores value elsewhere and trigger some required behaviour
>  >>> f.bar
> retrieve value from elsewhere and trigger some required behaviour
> 84
>  >>> f.__dict__
> {}
>  >>> f.bar = 33
> override __setattr_ for some reason
> stores value elsewhere and trigger some required behaviour
>  >>> f.bar
> retrieve value from elsewhere and trigger some required behaviour
> 66
>  >>> f.__dict__
> {}
>  >>> b = Baaz()
>  >>> b.__dict__
> {'bar': 42}
>  >>> b.bar
> retrieve value from elsewhere and trigger some required behaviour
>  >>> b.bar = 33
> override __setattr_ for some reason
>  >>> b.bar
> retrieve value from elsewhere and trigger some required behaviour
>  >>> b.__dict__
> {'bar': 42}

-- 
Terry Jan Reedy





More information about the Python-list mailing list