Can a descriptor auto-detect the name of an object passed to it?
class MyDecorator( object ):
def __init__(self, wrapped):
# Detect that wrapped's name is 'some_attr' here
开发者_StackOverflow中文版 pass
class SomeClass( object ):
some_attr = dict()
wrapper = MyDecorator( some_attr )
No, not really. You can hack something together with introspection of call frames, but it's not a nice -- or robust -- solution. (What would you do if SomeClass had two descriptors, some_attr=MyDecorator()
and someother_attr=some_attr
??)
It's better to be explicit:
def mydecorator(attr):
class MyDecorator( object ):
def __get__(self,inst,instcls):
print(attr)
return MyDecorator()
class SomeClass( object ):
some_attr = mydecorator('some_attr')
someother_attr = mydecorator('someother_attr')
s=SomeClass()
s.some_attr
# some_attr
s.someother_attr
# someother_attr
(Answering my own question for posterity.)
This is the best I've come up with so far:
class MyDecorator( object ):
def __init__(self, wrapped):
import inspect
for name, obj in inspect.stack(2)[1][0].f_locals.iteritems():
if wrapped is obj:
print "wrapped attribute is called", name
break
else:
raise RuntimeError("Failed to auto-detect attribute name")
精彩评论