Joe*_* M. 18 python methods class decorator python-decorators
我无法理解为什么会发生以下情况.我有一个装饰器,它除了检查函数是否是一个方法之外什么都不做.我以为我已经理解了Python中的哪种方法,但很明显,情况并非如此:
import inspect
def deco(f):
def g(*args):
print inspect.ismethod(f)
return f(*args)
return g
class Adder:
@deco
def __call__(self, a):
return a + 1
class Adder2:
def __call__(self, a):
return a + 2
Adder2.__call__ = deco(Adder2.__call__)
Run Code Online (Sandbox Code Playgroud)
现在,运行以下命令:
>>> a = Adder()
>>> a(1)
False
2
>>> a2 = Adder2()
>>> a2(1)
True
3
Run Code Online (Sandbox Code Playgroud)
我希望这段代码能够打印True两次.
那么,如在Adder2中手动装饰功能并不完全等同于通过@deco功能进行装饰?
有人可以这么高兴并解释为什么会这样吗?
Mar*_*ers 14
方法是与类关联的函数.只有从已定义的类中检索方法时才会创建方法; 方法是函数的包装器,同时引用类(以及可选的实例引用).
第一种情况会发生什么:Python编译您的类定义Adder.它找到装饰器定义和函数.装饰器传递函数,返回一个新函数.该函数被添加到类定义(存储在类中__dict__).你一直在处理python函数,而不是方法.这发生在以后.
然后a(1),当您调用时,查找显示该实例没有类__call__但Adder该类具有,因此使用它进行检索__getattribute__().这找到一个函数(你的deco装饰器),它是一个描述符,所以它的__get__()方法被调用(所以Adder.__call__.__get__(a, Adder)),返回一个绑定的方法,然后调用并传入1值.该方法被绑定,因为调用instance时不是None __get__().你的装饰器,它在类构建时包装了一个函数,False因为它是通过一个未包装的函数开始打印的.
在第二种情况下,但是,您检索方法(同样通过__getattribute__()调用__get__()在未修饰的Adder2.__call__功能),此时未绑定(因为没有实例,只传递给类__get__()(完整的呼叫Adder2.__call__.__get__(None, Adder2)),你再装点该方法.现在ismethod()打印True.
请注意,在Python 3中,后一种情况会发生变化.在Python 3中,不再存在未绑定方法的概念,只有函数和绑定方法.因此,"绑定"一词完全被删除.在这种情况下,您的第二种情况也会打印False为Adder2.__call__.__get__(None, Adder2)返回函数.
在类定义中,__call__是一个函数,而不是一个方法.通过属性查找(例如使用点语法)访问函数的行为(例如with Adder2.__call__)返回未绑定的方法.并a2.__call__返回一个绑定方法(带有self绑定a2).
请注意,在Python3中,概念unbound method已被删除.那里Adder2.__call__也是一个功能.
| 归档时间: |
|
| 查看次数: |
1139 次 |
| 最近记录: |