__set__ method is not called for class attribute access
Peter Otten
__peter__ at web.de
Fri Aug 5 08:10:52 EDT 2011
Ryan wrote:
> In the context of descriptors, the __set__ method is not called for
> class attribute access. __set__ is only
> called to set the attribute on an instance instance of the owner class
> to a new value, value. WHY? Is there some other mechanism for
> accomplishing this outcome. This subtle difference from __get__cost me
> some time to track down. Might think about pointing that out the
> documentation.
>
>
> class RevealAccess(object):
> """A data descriptor that sets and returns values
> normally and prints a message logging their access.
> """
>
> def __init__(self, initval=None, name='var'):
> self.val = initval
> self.name = name
>
> def __get__(self, obj, objtype):
> print 'Retrieving', self.name
> return self.val
>
> def __set__(self, obj, val):
> print 'Updating' , self.name
> self.val = val
>
> class MyClass(object):
> x = RevealAccess(10, 'var "x"')
> y = 5
>
> print MyClass.x
> MyClass.x = 20
> print MyClass.x
> MyClass.x = 30
> print MyClass.x
>
> Retrieving var "x"
> 10
> 20
> 30
>
> I am at a lost on how to intercept class attribute sets. Can anyone
> help :-/
A class is just an instance of its metaclass, so you could move the
descriptor into the metaclass to see the expected behaviour in the class:
>>> class A:
... class __metaclass__(type):
... x = RevealAccess(10, 'var "x"')
...
>>> A.x = 42
Updating var "x"
>>> A.x
Retrieving var "x"
42
However:
>>> A().x
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
AttributeError: 'A' object has no attribute 'x'
So you'd need two descriptors if you want to intercept variable access on
both the instance and class level.
More information about the Python-list
mailing list