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








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

Reply via email to