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