方法也是属性.它们恰好是可调用的对象.
>>> def foo(): pass
...
>>> callable(foo)
True
>>> callable(1)
False
调用方法时,查找属性(getattr()操作)然后调用结果:
c.setAttr(newvalue)
是两步;找到属性(在这种情况下查找类上的属性,并将其视为描述符),然后调用结果对象,即方法.
分配给属性时,将该名称重新绑定为新值:
c.setAttr = 'something else'
将是一个setattr()操作.
如果您想拦截获取和设置类实例的属性,可以提供attribute access hooks,__ getattr __,__ setattr__和__delattr__.
如果要向实例添加方法,则必须将该函数视为descriptor object,它会生成方法对象:
>>> class Foo: pass
...
>>> foo = Foo() # instance
>>> def bar(self): pass
...
>>> bar
>>> bar.__get__(foo,Foo)
>
函数.__ get __()的返回值,当给定实例和类时,是绑定方法.调用该方法将调用与实例自绑定的底层函数.
说到描述符,property() function也返回一个描述符,使得函数的行为类似于属性;他们可以截取该属性的getattr(),setattr()和delattr()操作并将其转换为函数调用:
>>> class Foo:
... @property
... def bar(self):
... return "Hello World!"
...
>>> foo = Foo()
>>> foo.bar
"Hello World!"
访问.bar调用了bar属性get hook,然后调用原始bar方法.
几乎在所有情况下,您都不需要callable()函数;您记录您的API,并提供方法和属性,API的用户将在不测试每个属性的情况下找出它以查看它是否可调用.使用属性,您可以灵活地提供在任何情况下都是真正可调用的属性.