In trying to support user requests for C++-like behavior of wrapped static data members, I noticed the following little assymetry:
#define a property class ... class Prop(object): ... def __get__(self, obj, type=None): ... print '__get__', (self, obj, type) ... return 'value' ... ... def __set__(self, obj, type=None): ... print '__set__', (self, obj, type) ... ... def __delete__(self, obj, type=None): ... print '__delete__', (self, obj, type) ... # use it in a class Y ... class Y(object): ... x = Prop() ... a = Y()
a.x # all accesses to a.x are intercepted __get__ (<__main__.Prop object at 0x00877BC8>, <__main__.Y object at 0x00878108>,
) 'value' a.x = 42 __set__ (<__main__.Prop object at 0x00877BC8>, <__main__.Y object at 0x00878108>, 42)
Y.x # Prop intercepts reads of the class attribute __get__ (<__main__.Prop object at 0x00877BC8>, None,
) 'value' Y.x = 1 # But not assignments Y.x 1
class mc(object.__class__): # to intercept Y.x assignment ... x = Prop() # I have to define this ... class Y(object): ... __metaclass__ = mc ... Y.x # now all accesses to Y.x are intercepted __get__ (<__main__.Prop object at 0x00876AB8>,
, ) 'value' Y.x = 1 __set__ (<__main__.Prop object at 0x00876AB8>, , 1) a = Y() # But not accesses to a.x a.x Traceback (most recent call last): File "<stdin>", line 1, in ? AttributeError: 'Y' object has no attribute 'x'
As you can see, the only way to intercept assignment to Y.x is to stick a property Y's class, i.e. the metaclass (or to modify __setattr__ in the metaclass, but it amounts to the same thing). In C++, a mutable static data member can be modified via the class Y::x = 1; or an instance of the class a.x = 1; I notice that Python supports this sort of dual access for reading attributes and calling static functions, but getting that behavior for mutable attributes seems unreasonably difficult: I need a property in the metaclass *and* in the class. 1. To throw out a straw-man suggestion, what about adding an additional protocol __set2__ which, if found, will be called instead of __set__ both for reading _and_ writing attributes on the class? 2. What are the optional type=None arguments for? It seems as though only the middle argument (obj) is ever None. I just copied this protocol out of descrintro.html 3. Is there documentation for __delete__ anywhere? -- Dave Abrahams Boost Consulting www.boost-consulting.com
participants (3)
-
Anthony Baxter
-
David Abrahams
-
Guido van Rossum