views:

95

answers:

1

I bumped into the following last night and I'm still at a loss as to explain it:

class Foo(object):
    @property
    def dave(self):
        vars(self)['dave'] = 1
        return 2

f = Foo()
print f.dave
print f.dave

Running this code produces:

2
2

The question is why? My understanding of attribute access is that the instance dictionary is checked before the class dictionary, and the dictionary of any bases, however as seen above the instance dictionary doesn't appear to be getting checked before the descriptor is found in the class dictionary.

+5  A: 

My understanding of attribute access is that the instance dictionary is checked before the class dictionary, and the dictionary of any bases

Data descriptors are an exception:

For instance bindings, the precedence of descriptor invocation depends on the which descriptor methods are defined. Normally, data descriptors define both __get__() and __set__(), while non-data descriptors have just the __get__() method. Data descriptors always override a redefinition in an instance dictionary. In contrast, non-data descriptors can be overridden by instances.

http://docs.python.org/reference/datamodel.html#invoking-descriptors

Miles
Thanks! I swear I tried the docs earlier. :) Guess there's magic going on underneath the covers that I haven't even scratched the surface of.
David Wilson
@David Wilson: No magic. But when you're trying to have a method function as a property that updates *itself* you're doing something too complex. Perhaps if you used different names for the function and the property, you'd find that there was no magic.
S.Lott