Propert handler question

Discussion in 'Python' started by user@domain.invalid, Oct 30, 2003.

  1. Guest

    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.

    Thanks,

    Toby
     
    , Oct 30, 2003
    #1
    1. Advertising

  2. On Thu, 30 Oct 2003 20:52:28 GMT, lid 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 don't think so, though I could be wrong.

    I'd write one main getter/setter function with an extra parameter for
    the property name, then add a whole bunch of noddy getter/setter
    functions that provide that extra parameter. Or perhaps a number of
    extra parameters - flags to control specific parts of the handlers -
    would work better.


    --
    Steve Horne

    steve at ninereeds dot fsnet dot co dot uk
     
    Stephen Horne, Oct 31, 2003
    #2
    1. Advertising

  3. John Roth Guest

    <> wrote in message
    news:...
    > 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.


    The only thing that occurs to me is looking up the call
    stack to find what was being accessed. Somehow, that
    seems to be the wrong way to approach the problem,
    though.

    You might want to look at the __getattr__() and
    ___setattr() magic methods defined in the Python
    Language Reference manual (section 3.3.3 in the
    Python 2.2.3 manual set.) These are not the easiest
    things in the world to program correctly, (setattr in
    particular is prone to loops unless you do everything
    exactly right) but they
    might be what you need in this case, rather than
    a boatload of properties.

    John Roth
    >
    > Thanks,
    >
    > Toby
    >
     
    John Roth, Oct 31, 2003
    #3
  4. On Thu, 30 Oct 2003 20:52:28 GMT, lid 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
     
    Bengt Richter, Oct 31, 2003
    #4
  5. lid 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.


    So use a closure. E.g, trivial example:

    def prop(name):
    def getter(self):
    print 'getting', name
    return getattr(self, '_'+name)
    def setter(self, value):
    print 'setting', name, 'to', value
    return setattr(self, '_'+name, value)
    return getter, setter

    class WithProperties(object):
    foo = property(*prop('foo'))
    bar = property(*prop('bar'))
    baz = property(*prop('baz'))

    w = WithProperties()
    w.foo = w.bar = 23
    print w.foo, w.bar

    will emit:

    [alex@lancelot bo]$ python proe.py
    setting foo to 23
    setting bar to 23
    getting foo
    23 getting bar
    23


    Yes, this does require a double specification of the name -- as
    an argument to prop AND as the thing you assign to in classbody.

    Avoiding this requires black or at least dark-grayish magic, such
    as (I've seen others already suggest somewhat-more-magic-yet
    solutions requiring both custom metaclasses and custom descriptors,
    this one at least makes do with a custom metaclass and a descriptor
    _helper_ that gets turned into an ordinary property descriptor:)...:

    class magicprop(object):
    def __init__(self, name=''): self.name = name
    def getter(self, other):
    print 'getting', self.name
    return getattr(other, '_'+self.name)
    def setter(self, other, value):
    print 'setting', self.name, 'to', value
    return setattr(other, '_'+self.name, value)

    class magicmeta(type):
    def __new__(mcl, clasname, clasbase, clasdict):
    for n, v in clasdict.items():
    if not isinstance(v, magicprop): continue
    v.name = n
    clasdict[n] = property(v.getter, v.setter)
    return type.__new__(mcl, clasname, clasbase, clasdict)

    class magic: __metaclass__ = magicmeta

    class WithProperties(magic):
    foo = magicprop()
    bar = magicprop()
    baz = magicprop()

    w = WithProperties()
    w.foo = w.bar = 23
    print w.foo, w.bar


    this gives the same output as before.

    If you do a lot of this you probably don't want to code the
    getters and setters right inside the magicprop helper, of
    course, but rather code them in the target class and pass
    them to magicprop as you'd normally pass them to property.
    No problem, actually...:

    class magicprop(object):
    def __init__(self, getter, setter, name=''):
    self.name = name
    self.getter = getter
    self.setter = setter
    def get(self, other):
    return self.getter(other, self.name)
    def set(self, other, value):
    return self.setter(other, self.name, value)

    class magicmeta(type):
    def __new__(mcl, clasname, clasbase, clasdict):
    for n, v in clasdict.items():
    if not isinstance(v, magicprop): continue
    v.name = n
    clasdict[n] = property(v.get, v.set)
    return type.__new__(mcl, clasname, clasbase, clasdict)

    class magic: __metaclass__ = magicmeta

    class WithProperties(magic):
    def getter(self, name):
    print 'getting', name
    return getattr(self, '_'+name)
    def setter(self, name, value):
    print 'setting', name, 'to', value
    setattr(self, '_'+name, value)
    foo = magicprop(getter, setter)
    bar = magicprop(getter, setter)
    baz = magicprop(getter, setter)

    w = WithProperties()
    w.foo = w.bar = 23
    print w.foo, w.bar


    and again the output is as usual.


    Alex
     
    Alex Martelli, Oct 31, 2003
    #5
    1. Advertising

Want to reply to this thread or ask your own question?

It takes just 2 minutes to sign up (and it's free!). Just click the sign up button to choose a username and then you can ask your own questions on the forum.
Similar Threads
  1. shruds
    Replies:
    1
    Views:
    894
    John C. Bollinger
    Jan 27, 2006
  2. Lars Kellogg-Stedman

    MacOS/NeXTStep propert list parsing?

    Lars Kellogg-Stedman, Sep 8, 2003, in forum: Python
    Replies:
    1
    Views:
    389
  3. Replies:
    1
    Views:
    735
    Damien
    Feb 22, 2007
  4. Java Guy
    Replies:
    1
    Views:
    702
    Manish Pandit
    Oct 15, 2006
  5. Java Guy
    Replies:
    1
    Views:
    325
Loading...

Share This Page