kin*_*all 46 python properties
如果我有这个:
class foo(object):
@property
def bar(self):
return 0
f = foo()
Run Code Online (Sandbox Code Playgroud)
如果可能的话,如何在不实际调用方法的情况下获得对f.bar的引用?
编辑添加:我想要做的是编写一个函数,迭代f的成员并对它们做一些事情(什么是不重要的).属性让我失望,因为只需在getattr()中命名它们就会调用它们的__get __()方法.
unu*_*tbu 37
get_dict_attr(下面)attr在给定对象中查找__dict__,并返回相关值(如果在那里).如果attr不是那里的关键,则搜索__dict__对象的MRO __dict__.如果找不到密钥,AttributeError则会引发a.
def get_dict_attr(obj, attr):
for obj in [obj] + obj.__class__.mro():
if attr in obj.__dict__:
return obj.__dict__[attr]
raise AttributeError
Run Code Online (Sandbox Code Playgroud)
例如,
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
Run Code Online (Sandbox Code Playgroud)
请注意,这与属性查找的常规规则非常不同.首先,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()
Run Code Online (Sandbox Code Playgroud)
这引用了该属性bar:
print(Foo.bar)
# <property object at 0xb76d1d9c>
Run Code Online (Sandbox Code Playgroud)
你看到的bar是一个关键Foo.__dict__:
print(Foo.__dict__['bar'])
# <property object at 0xb775dbbc>
Run Code Online (Sandbox Code Playgroud)
所有属性都是描述符,这意味着它有一个__get__方法:
print(Foo.bar.__get__)
# <method-wrapper '__get__' of property object at 0xb76d7d74>
Run Code Online (Sandbox Code Playgroud)
您可以通过传递对象f和f作为参数的类来调用该方法:
print(Foo.bar.__get__(f,Foo))
# 0
Run Code Online (Sandbox Code Playgroud)
我喜欢下面的图表.垂直线表示对象与对象类之间的关系.
遇到这种情况时:
Foo B
| Foo.__dict__={'bar':b} | B.__dict__={'__get__':...}
| \ |
f `--------> b
Run Code Online (Sandbox Code Playgroud)
f.bar导致b.__get__(f,Foo)被调用.
这在详细解释这里.
就你而言,
class Foo(object):
@property
def bar(self):
return 0
f = Foo()
Run Code Online (Sandbox Code Playgroud)
您可以通过 Foo 类访问该属性。这些都是等价的:
Foo.bar
Foo.__dict__['bar']
f.__class__.__dict__['bar']
=> <property at 0x4920c28>
Run Code Online (Sandbox Code Playgroud)
正如您所看到的,这是一个property实例。在属性上,您有一个调用的方法fget,该方法返回“getter”值。
isinstance(Foo.bar, property)
=> True
Foo.bar.fget
=> <function Foo.bar at 0x0000014DC0CF21F0>
Run Code Online (Sandbox Code Playgroud)
您可以直接调用该函数(实例方法)。Foo.bar.fget(f) => 0
注意:您必须向自己提供对象f(self参数)fget,因为当通过类访问时,该类还不知道实例f。换句话说,实例方法Foo.bar.fget尚未“绑定”到f.
我遇到了与此类似的情况,其他答案都没有帮助我,所以这是另一种方法。
我的情况略有不同,因为我不是只有一个@property,而是混合了一个自定义装饰器,该装饰器向包装的方法添加属性。所以例如通常我会有这样的东西:
class Foo:
@my_decorator
def bar(self):
return do_stuff() # Pretend this is non-trivial
Run Code Online (Sandbox Code Playgroud)
然后我@my_decorator会让我访问self.bar.my_attribute那些我有时需要访问的数据。这对于函数和方法非常有效,但在尝试将其混合时我遇到了障碍,@property因为该属性隐藏了对方法的引用(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
Run Code Online (Sandbox Code Playgroud)
然后解决方案是访问my_attributeas Foo.bar.fget.my_attribute(这里重要的细节是从类访问属性返回属性对象,而从实例访问属性只是调用方法并返回值,而不访问原始引用方法)。
TL;DR:如果您需要对提供 的方法的引用@property,则需要使用YourClassName.your_property.fget.
简短的回答:
属性在从类中调用时返回自身: MyClass.my_prop
此外,它们的字段包含指向实际方法的链接:fget、fset和fdel。
描述:
所以,my_class.my_prop(where my_class = MyClass()) 返回值,但MyClass.my_prop返回属性对象并MyClass.my_prop.fget返回此属性的 getter 方法。在self没有连接到它,所以它应该在通话过程中填充:MyClass.my_prop.fget(my_class)
例子:
class MyClass:
my_prop = property(lambda self: 'get', lambda self, x: print('set', x))
setter = MyClass.my_prop.fset
getter = MyClass.my_prop.fget
my_class = MyClass()
setter(my_class, 5) # equals my_class.my_prop = 5
print(getter(my_class)) # equals print(my_class.my_prop)
Run Code Online (Sandbox Code Playgroud)
| 归档时间: |
|
| 查看次数: |
15926 次 |
| 最近记录: |