Detect target name in descriptor __set__ method

G

Gabriel Genellina

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):
print 'descriptor.__get__ self=%r instance=%r owner=%r' % (
self, instance, owner)
return self

def __set__(self, instance, value):
# I want to know the *name* this value is being assigned to
print 'descriptor.__set__ self=%r instance=%r value=%r' % (
self, instance, value)

def __delete__(self, instance):
print 'descriptor.__delete__ self=%r instance=%r' % (
self, instance)

class X(object):
foo = descriptor()

x = X()
x.foo = "value"


I can obtain the name descriptor() was assigned to at the time the X class
was defined, using a custom metaclass:


class Meta(type):
def __new__(meta, name, bases, dict):
for key,value in dict.iteritems():
if isinstance(value, descriptor):
value.name = key
return type.__new__(meta, name, bases, dict)

class Y(object):
__metaclass__ = Meta
foo = descriptor()

y = Y()
print y.foo.name # prints 'foo'


This is good enough for me (assuming no one modifies the class after
defining it, no two names refer to the same descriptor, no two classes
share the same descriptor instance...). But I would like to use a more
direct/robust approach, if available.

Any ideas?
 
J

Jon Clements

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):
     print 'descriptor.__get__ self=%r instance=%r owner=%r' % (
       self, instance, owner)
     return self

   def __set__(self, instance, value):
     # I want to know the *name* this value is being assigned to
     print 'descriptor.__set__ self=%r instance=%r value=%r' % (
       self, instance, value)

   def __delete__(self, instance):
     print 'descriptor.__delete__ self=%r instance=%r' % (
       self, instance)

class X(object):
   foo = descriptor()

x = X()
x.foo = "value"

I can obtain the name descriptor() was assigned to at the time the X class  
was defined, using a custom metaclass:

class Meta(type):
   def __new__(meta, name, bases, dict):
     for key,value in dict.iteritems():
       if isinstance(value, descriptor):
         value.name = key
     return type.__new__(meta, name, bases, dict)

class Y(object):
   __metaclass__ = Meta
   foo = descriptor()

y = Y()
print y.foo.name # prints 'foo'

This is good enough for me (assuming no one modifies the class after  
defining it, no two names refer to the same descriptor, no two classes  
share the same descriptor instance...). But I would like to use a more  
direct/robust approach, if available.

Any ideas?
def __setattr__(self, what, value):
print what, value

foo x

Is that what you're after?

Jon.
 
G

Gabriel Genellina

def __setattr__(self, what, value):
print what, value


foo x

Is that what you're after?

Yes and no. __setattr__ has a terrible overhead as it is invoked for each
and every attribute being set, special or not. Using a custom descriptor
seems better, because it allows to intercept just the desired attribute.
If only I had access to the name being used...
 

Ask a Question

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

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

Forum statistics

Threads
473,769
Messages
2,569,580
Members
45,054
Latest member
TrimKetoBoost

Latest Threads

Top