properties + types, implementing meta-class desciptors elegantly?
Mike C. Fletcher
mcfletch at rogers.com
Mon Jul 21 18:33:27 EDT 2003
Michael Hudson wrote:
>Michael Hudson <mwh at python.net> writes:
>
>
>
>>"Mike C. Fletcher" <mcfletch at rogers.com> writes:
>>
>>
>>
>>>So, does anyone have a pattern which allows setting an attribute on
>>>a class which doesn't go through the setattr machinery (i.e. can be
>>>used within a descriptor)?
>>>
>>>
>>No. Fun problem to think about, though :-)
>>
>>
>
>Actually, that was a lie. Check this horror out:
>
<snip>
>I'm quite proud of this one :-)
>
Rightly so, all evil geniuses should always gloat over their mad
creations :) . Unfortunately, it appear to tickle a Python 2.2.3 bug
where setting a descriptor on a meta-class doesn't reinstate capturing
of the __get__ for the attribute. I filed a bug report for that here:
https://sourceforge.net/tracker/index.php?func=detail&aid=775328&group_id=5470&atid=105470
Other than that, and it's intrinsicly *evil* nature, it does, indeed, do
what I was looking for.
BTW, you're creating a property whose *value* (albeit a static value) is
shared by all instances of the meta-class, rather than one that's
specific to the individual class. Here's code that, if the bug above
weren't active would do the more "normal" per-instance property pattern
(with the same evil mechanism):
class MetaProp(object):
def __init__(self, val):
self.val = val
def __get__(self, ob, cls=None):
print 'metaprop get'
for k in ob.__class__.__dict__:
if ob.__class__.__dict__[k] is self:
delattr(ob.__class__, k)
break
else:
raise Exception, 'not found'
newValue = ob.__dict__.get( k, self.val) + 1
setattr(ob, k, newValue)
setattr(ob.__class__, k, self)
return newValue
class Meta(type):
p = MetaProp(1)
class C:
__metaclass__ = Meta
class D:
__metaclass__ = Meta
print C.__dict__.keys()
print C.p
print C.__dict__.keys()
print C.p
print C.p
print D.p
print D.p
On Python 2.2.3 that prints out (showing the bug above):
P:\temp>metaprop.py
['__dict__', '__weakref__', '__module__', '__metaclass__', '__doc__']
metaprop get
2
['p', '__module__', '__metaclass__', '__dict__', '__weakref__', '__doc__']
2
2
metaprop get
2
2
But really, I don't think either of us will deploy that particular
pattern in a production system. Still, fun proposal, thanks for
playing, we have lots of marvelous parting gifts for you :) .
BTW: You know this, but in case others are wondering why it's not usable
in real life: it's possible to have threads get/set the value without
triggering the descriptor if they happen to ask for it during the period
when the descriptor is deleted.
Enjoy,
Mike
_______________________________________
Mike C. Fletcher
Designer, VR Plumber, Coder
http://members.rogers.com/mcfletch/
More information about the Python-list
mailing list