Propert handler question

Collapse
This topic is closed.
X
X
 
  • Time
  • Show
Clear All
new posts
  • user@domain.invalid

    Propert handler question

    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

  • Stephen Horne

    #2
    Re: Propert handler question

    On Thu, 30 Oct 2003 20:52:28 GMT, user@domain.inv alid wrote:
    [color=blue]
    >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.[/color]

    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

    Comment

    • John Roth

      #3
      Re: Propert handler question


      <user@domain.in valid> wrote in message
      news:e2c8c0a72d 718c83d1adfe080 f1497a8@news.te ranews.com...[color=blue]
      > 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.[/color]

      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[color=blue]
      >
      > Thanks,
      >
      > Toby
      >[/color]


      Comment

      • Bengt Richter

        #4
        Re: Propert handler question

        On Thu, 30 Oct 2003 20:52:28 GMT, user@domain.inv alid wrote:
        [color=blue]
        >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.
        >[/color]
        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



        to whom thanks. Also you may want to read

        The official home of the Python Programming Language


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

        ====< namedprop.py >============== =============== =============== ===========
        class NamedProp(prope rty):
        def __get__(pself, oself, otype=None):
        """NamedPro p 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):
        """NamedPro p setter"""
        # customize as desired
        oself._pval = val
        def __init__(pself, name):
        """Give property instance a name"""
        pself.name = name

        class MC_AddNamedProp s(type):
        """Automate adding a list of named properties with shared getter/setter code"""
        def __new__(cls, cname, cbases, cdict):
        for name in cdict.get('__pr oplist__',[]):
        cdict[name]=NamedProp(name )
        return type.__new__(cl s, cname, cbases, cdict)

        class Test(object):
        """Example class with name-carrying properties"""
        __metaclass__ = MC_AddNamedProp s
        __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\des cr>namedprop.py
        t1: <__main__.Tes t 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

        Comment

        • Alex Martelli

          #5
          Re: Propert handler question

          user@domain.inv alid wrote:
          [color=blue]
          > 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.[/color]

          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(objec t):
          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.gett er, v.setter)
          return type.__new__(mc l, 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(objec t):
          def __init__(self, getter, setter, name=''):
          self.name = name
          self.getter = getter
          self.setter = setter
          def get(self, other):
          return self.getter(oth er, self.name)
          def set(self, other, value):
          return self.setter(oth er, 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__(mc l, 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(gette r, setter)
          bar = magicprop(gette r, setter)
          baz = magicprop(gette r, setter)

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


          and again the output is as usual.


          Alex

          Comment

          Working...