newbie: class and __dict__ variable.

Bruno Desthuilliers bruno.42.desthuilliers at websiteburo.invalid
Mon Sep 20 11:51:53 CEST 2010


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...


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}
 >>>











More information about the Python-list mailing list