Detect target name in descriptor __set__ method

DG dangets at gmail.com
Thu Jul 23 12:21:15 EDT 2009


On Jul 23, 8:44 am, Rainer Mansfeld <MLi... at romulo.de> wrote:
> Gabriel Genellina schrieb:
>
> > I have a class attribute 'foo' which is a data descriptor. I create an
> > instance of such class. When I say instance.foo = value, the descriptor
> > __set__ method is called. Is there any way to obtain the name being
> > assigned to? ('foo' in this example). That is, I want to know the target
> > name for the assignment that triggered the __set__ method call.
>
> class descriptor(object):
>      def __get__(self, instance, owner):
>        return self
>
>      def __set__(self, instance, value):
>          # I want to know the *name* this value is being assigned to
>          for name in instance.__class__.__dict__:
>              if getattr(instance, name) is self:
>                  print "assigning to %s" % name
>                  break
>
> class X(object):
>      foo = descriptor()
>      bar = descriptor()
>
> class Y(object):
>      foo = descriptor()
>      baz = descriptor()
>
> x = X()
> y = Y()
>
> x.foo = "value"
> x.bar = "value"
> y.foo = "value"
> y.baz = "value"
>
> Does this work for you?
>
>     Rainer

The reason I wasn't checking the class' '__dict__' attribute in my
solution was because this won't show any descriptors that were
inherited from base classes.  Example with some optimizations below
(sorry for the long code):

builtin_methods = dir(object)

class descriptor(object):
    def __init__(self):
        self.name = None

    def __get__(self, instance, owner):
        # if you want a 'useful' data descriptor only return self upon
        # non-instance access
        if instance is None:
            return self
        else:
            # do something besides the below for the usefulness
            return self

    def __set__(self, instance, value):
        if self.name is None:
            cls = instance.__class__
            dir_attrs = [m for m in dir(cls) if m not in
builtin_methods]
            # 'foo' is printed here
            print 'dir(cls):    ', dir_attrs
            # 'foo' is not printed here
            print 'cls.__dict__:', cls.__dict__
            for name in dir_attrs:
                if getattr(cls, name) is self:
                    self.name = name
        print "setting %s to %s" % (self.name, value)


class baseX(object):
    foo = descriptor()

class X(baseX):
    pass

x = X()
x.foo = 'bar'




More information about the Python-list mailing list