方法也是属性。它们恰好是可调用对象。
callable()
您可以使用以下函数检测对象是否可调用:
>>> def foo(): pass
...
>>> callable(foo)
True
>>> callable(1)
False
调用方法时,查找属性(getattr()
操作),然后调用结果:
c.setAttr(newvalue)
是两个步骤;找到属性(在这种情况下查找类上的属性,并将其视为描述符),然后调用生成的对象,即方法。
当您分配给一个属性时,您将该名称重新绑定到一个新值:
c.setAttr = 'something else'
将是一个setattr()
操作。
如果你想拦截类实例的获取和设置属性,你可以提供属性访问钩子、__getattr__
和。__setattr__
__delattr__
如果你想给一个实例添加一个方法,你必须把这个函数当作一个描述符对象,它会产生一个方法对象:
>>> class Foo: pass
...
>>> foo = Foo() # instance
>>> def bar(self): pass
...
>>> bar
<function bar at 0x10b85a320>
>>> bar.__get__(foo, Foo)
<bound method Foo.bar of <__main__.Foo instance at 0x10b85b830>>
的返回值function.__get__()
,当给定一个实例和一个类时,是一个绑定方法。调用该方法将调用self
绑定到实例的底层函数。
说到描述符,该property()
函数也返回一个描述符,这使得具有行为类似属性的函数成为可能;他们可以拦截该属性的getattr()
,setattr()
和delattr()
操作并将其转换为函数调用:
>>> class Foo:
... @property
... def bar(self):
... return "Hello World!"
...
>>> foo = Foo()
>>> foo.bar
"Hello World!"
访问.bar
调用bar
属性 get 钩子,然后调用原始bar
方法。
在几乎所有情况下,您都不需要该callable()
功能。您记录您的 API,并提供方法和属性,并且您的 API 的用户会弄清楚它,而无需测试每个属性以查看它是否可调用。使用属性,您可以灵活地提供在任何情况下真正可调用的属性。