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


--
http://mail.python.org/mailman/listinfo/python-list

Reply via email to