Propert handler question

Bengt Richter bokr at oz.net
Fri Oct 31 01:35:57 EST 2003


On Thu, 30 Oct 2003 20:52:28 GMT, user at domain.invalid wrote:

>Is there a way, from within a getter/setter method
>linked to a propert, that I can tell which property
>triggered the method?
>
>This would be great, because I need a great number
>of these properties, each having only slightly different
>actions, which could be triggered correctly if
>I knew the name of the property that was being accessed.
>
I think you might want to make a custom descriptor class whose
instances you can give names the same as the property they implement.
The get and set methods are the same, but have access to the name parameter
saved in the descriptor instance. E.g., (note that there are two instance "selves"
involved -- the self of the descriptor/property where the individual name is stored,
and the self of the object normally passed to a getter function, but here just
implemented in line, since it is the same for all the descriptor instances in this case.

The following might give you some ideas. The metaclass thing was just to avoid
definining the properties one by one like

class Test(object):
    foo = NamedProp('foo')
    bar = NamedProp('bar')
    baz = NamedProp('baz')
    ...

(you said there might be a lot of them, so I thought __proplist__ = 'foo bar baz'.split()
would be easier and guarantee the matching of the names bound with the strings passed to the
NamedProp constructor).

A good writeup on the descriptor stuff is Raymond Hettinger's

    http://users.rcn.com/python/download/Descriptor.htm

to whom thanks. Also you may want to read

    http://www.python.org/2.2.2/descrintro.html

(Hope I haven't misled with the following. Caveat lector? ;-)

====< namedprop.py >=======================================================
class NamedProp(property):
    def __get__(pself, oself, otype=None):
        """NamedProp getter"""
        if oself is None:
            return pself         
        # implement shared getter code here
        # note property instance pself, and object instance oself both available
        return pself.name, oself._pval # example of value depending on both
    def __set__(pself, oself, val):
        """NamedProp setter"""
        # customize as desired
        oself._pval = val
    def __init__(pself, name):
        """Give property instance a name"""
        pself.name = name
        
class MC_AddNamedProps(type):
    """Automate adding a list of named properties with shared getter/setter code"""
    def __new__(cls, cname, cbases, cdict):
        for name in cdict.get('__proplist__',[]):
            cdict[name]=NamedProp(name)
        return type.__new__(cls, cname, cbases, cdict)
 
class Test(object):
    """Example class with name-carrying properties"""
    __metaclass__ = MC_AddNamedProps
    __proplist__ = 'foo bar baz'.split()
    def __init__(self, val=None): self._pval=val

def test():
    t1 = Test(111)
    print 't1:',t1
    print 't1.foo => %r' % (t1.foo,)
    print 't1.bar => %r' % (t1.bar,)
    print 't1.baz => %r' % (t1.baz,)
    print 't1.foo = <new value via t1.foo> =>'
    t1.foo = '<new value via t1.foo>'
    print 't1.foo => %r' % (t1.foo,)
    print 't1.bar => %r' % (t1.bar,)
    print 't1.baz => %r' % (t1.baz,)
if __name__ == '__main__':
    test()
====< namedprop.py >=======================================================

Result:

[22:35] C:\pywk\clp\descr>namedprop.py
t1: <__main__.Test object at 0x0090B310>
t1.foo => ('foo', 111)
t1.bar => ('bar', 111)
t1.baz => ('baz', 111)
t1.foo = <new value via t1.foo> =>
t1.foo => ('foo', '<new value via t1.foo>')
t1.bar => ('bar', '<new value via t1.foo>')
t1.baz => ('baz', '<new value via t1.foo>')

Regards,
Bengt Richter




More information about the Python-list mailing list