我可以获得对Python属性的引用吗?
如果我有这个:
class foo(object): @property def bar(self): return 0 f = foo() 如果没有实际调用方法,如何获得对f.bar的引用?
编辑添加:我想要做的是写一个函数,迭代f的成员,并与他们做什么(什么是不重要的)。 属性让我跳了起来,因为只是在getattr()中命名它们就会调用它们的__get __()方法。
  get_dict_attr (下面)在给定对象的__dict__查找attr ,并返回关联值(如果存在)。 如果attr不是__dict__的关键字,则search该对象的MRO的__dict__ 。 如果找不到密钥,则会引发AttributeError 。 
 def get_dict_attr(obj, attr): for obj in [obj] + obj.__class__.mro(): if attr in obj.__dict__: return obj.__dict__[attr] raise AttributeError 
例如,
 class Foo(object): x=1 def bar(self): pass @property def baz(self): return 0 foo=Foo() print(get_dict_attr(foo,'x')) # 1 print(get_dict_attr(foo,'bar')) # <unbound method Foo.bar> print(get_dict_attr(foo,'baz')) # <property object at 0xb77c0dc4> print(get_dict_attr(foo,'y')) # AttributeError 
 请注意,这与属性查找的常规规则非常不同。 首先, obj.__class__.__dict__数据描述符(带有__get__和__set__方法的描述符)通常优先于obj.__dict__值。 在get_dict_attr , obj.__dict__具有优先权。 
  get_dict_attr不会尝试调用__getattr__ 。 
 最后, get_dict_attr只能用于obj ,它们是新风格类的实例。 
不过,我希望这是一些帮助。
 class Foo(object): @property def bar(self): return 0 f = Foo() 
 这引用了属性bar : 
 print(Foo.bar) # <property object at 0xb76d1d9c> 
 你看吧是Foo.__dict__一个关键Foo.__dict__ : 
 print(Foo.__dict__['bar']) # <property object at 0xb775dbbc> 
 所有属性都是描述符,这意味着它有一个__get__方法: 
 print(Foo.bar.__get__) # <method-wrapper '__get__' of property object at 0xb76d7d74> 
 您可以通过传递对象f和f的类作为参数来调用该方法: 
 print(Foo.bar.__get__(f,Foo)) # 0 
我喜欢以下图表。 垂直线显示对象和对象的类之间的关系。
当你有这种情况:
  Foo B | Foo.__dict__={'bar':b} | B.__dict__={'__get__':...} | \ | f `--------> b 
  f.bar导致b.__get__(f,Foo)被调用。 
这在这里详细解释。
在你的情况下,
 class foo(object): @property def bar(self): return 0 f = foo() 
您可以通过类的字典访问该属性:
 f.__class__.__dict__['bar'] => <property at 0x4920c28> 
 正如你所看到的,这是一个property实例。 
 isinstance(f.__class__.__dict__['bar'], property) => True 
 你可以像这样通过fget访问它的getter方法(它会return 0 ): 
 f.__class__.__dict__['bar'].fget(f) => 0 
 请注意,您必须将实例f给fget()因为它是一个实例方法(非静态),您可以通过__class__访问它。 
我碰到类似的情况,没有其他答案帮助我,所以这里有一个替代方法。
 我的情况稍有不同,因为我不是只拥有一个@property ,而是在一个定制的装饰器中混合,这个装饰器为包装的方法添加了属性。 所以通常我会有这样的东西: 
 class Foo: @my_decorator def bar(self): return do_stuff() # Pretend this is non-trivial 
 然后,我的@my_decorator会让我访问self.bar.my_attribute ,它有一些我需要访问的数据。 这对于函数和方法非常适用,但是当我试图将它与self.bar.my_attribute混合使用时遇到了一些问题,因为属性隐藏了对方法的引用( self.bar.my_attribute失败,因为self.bar返回方法的返回值,没有我想要的my_attribute )。 
 我会使用@property作为外部装饰器,如下所示: 
 class Foo: @property @my_decorator def bar(self): return do_stuff() # Pretend this is non-trivial 
 然后解决scheme是访问my_attribute作为Foo.bar.fget.my_attribute (这里重要的细节是从类访问属性返回属性对象,而从实例访问属性只是调用该方法并返回值,无需访问原始方法的参考)。 
  TL; DR:如果您需要提供您的@property的方法的引用,则需要使用YourClassName.your_property.fget 。 
有一件事你应该知道的是,数据描述符(即属性)只适用于(新风格)的类(见http://docs.python.org/reference/datamodel.html#implementing-descriptors )。 将它们复制到对象将不会在该对象上创build属性。 您需要将它们复制到(新式)类才能生效。
 class A: prop = property(lambda self: 'get', lambda self, x: print('set', x)) setter = A.prop.fset getter = A.prop.fget my_a = A() setter(my_a, 5) print(getter(my_a)) 
我会说忽略其他答案,因为他们是不好的。
 您可以通过foo.bar获得对该属性的foo.bar 
 至于你想要做什么迭代f的成员,请参阅下面的具体细节。 
长的回答:你必须明白的是,Python中的方法不属于实例,而是类对象的属性。 例如,
 class Foo: def bar(self): pass foo = Foo() 
 如果你调用foo.bar() ,Python首先检查foo是否有bar (不),然后检查Foo是否有bar ,它是foo.bar() 。 然后Python将foo.bar “绑定”到Foo.bar(foo) ,然后调用它。 
 属性也是如此。 我不知道确切的过程(我想它在实现中有所不同),但是本质上Python寻找foo.bar ,然后Foo.bar看到它是一个属性,所以评估它的getter并返回它。