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