您正在一个实例上调用dis.dis(); memoized 装饰器是一个类,memoized(function) 返回该类的一个实例。
例如,instance.__dict__ 对象的值中的所有代码或函数对象都被反汇编(因为dis() 函数假定它正在处理一个类)。由于原始函数是代码对象,因此将其反汇编。就好像你打电话给dis.dis(f.func);这就是为什么dis.dis() 输出以Disassembly of func 行开头的原因。
如果您想显示memoized.__call__ 方法的字节码,您必须在memoized 类上调用dis.dis()(并查看__init__ 和__call__ 的反汇编),或者反汇编直接使用memoized.__call__ 方法,通过使用dis.dis(memoized.__call__) 或dis.dis(fibonacci.__call__) 为反汇编程序提供对未绑定或绑定方法的引用。
由于装饰只是语法糖,用于调用传入函数的另一个对象,然后用结果替换该函数,因此不存在将装饰器与原始函数一起反汇编的事情.你能做的最好的就是分别反汇编可调用的装饰器和原始函数:
>>> dis.dis(fibonacci.__call__)
15 0 LOAD_GLOBAL 0 (isinstance)
3 LOAD_FAST 1 (args)
6 LOAD_GLOBAL 1 (collections)
9 LOAD_ATTR 2 (Hashable)
12 CALL_FUNCTION 2
15 POP_JUMP_IF_TRUE 31
18 18 LOAD_FAST 0 (self)
21 LOAD_ATTR 3 (func)
24 LOAD_FAST 1 (args)
27 CALL_FUNCTION_VAR 0
30 RETURN_VALUE
19 >> 31 LOAD_FAST 1 (args)
34 LOAD_FAST 0 (self)
37 LOAD_ATTR 4 (cache)
40 COMPARE_OP 6 (in)
43 POP_JUMP_IF_FALSE 71
20 46 LOAD_CONST 1 ('get cached version{}')
49 LOAD_ATTR 5 (format)
52 LOAD_FAST 1 (args)
55 CALL_FUNCTION 1
58 PRINT_ITEM
59 PRINT_NEWLINE
21 60 LOAD_FAST 0 (self)
63 LOAD_ATTR 4 (cache)
66 LOAD_FAST 1 (args)
69 BINARY_SUBSCR
70 RETURN_VALUE
23 >> 71 LOAD_CONST 2 ('compute {}')
74 LOAD_ATTR 5 (format)
77 LOAD_FAST 1 (args)
80 CALL_FUNCTION 1
83 PRINT_ITEM
84 PRINT_NEWLINE
24 85 LOAD_FAST 0 (self)
88 LOAD_ATTR 3 (func)
91 LOAD_FAST 1 (args)
94 CALL_FUNCTION_VAR 0
97 STORE_FAST 2 (value)
25 100 LOAD_FAST 2 (value)
103 LOAD_FAST 0 (self)
106 LOAD_ATTR 4 (cache)
109 LOAD_FAST 1 (args)
112 STORE_SUBSCR
26 113 LOAD_FAST 2 (value)
116 RETURN_VALUE
117 LOAD_CONST 0 (None)
120 RETURN_VALUE
>>> dis.dis(fibonacci.func)
39 0 LOAD_FAST 0 (n)
3 LOAD_CONST 4 ((0, 1))
6 COMPARE_OP 6 (in)
9 POP_JUMP_IF_FALSE 16
40 12 LOAD_FAST 0 (n)
15 RETURN_VALUE
41 >> 16 LOAD_GLOBAL 0 (fibonacci)
19 LOAD_FAST 0 (n)
22 LOAD_CONST 2 (1)
25 BINARY_SUBTRACT
26 CALL_FUNCTION 1
29 LOAD_GLOBAL 0 (fibonacci)
32 LOAD_FAST 0 (n)
35 LOAD_CONST 3 (2)
38 BINARY_SUBTRACT
39 CALL_FUNCTION 1
42 BINARY_ADD
43 RETURN_VALUE
您可以从 fibonacci.__call__ 反汇编中看到它会调用 self.func()(字节码 18 到 27),这就是为什么您会查看 fibonacci.func。
对于使用闭包的 function 装饰器,您必须通过查看 __closure__ 对象进入包装闭包以提取原始函数:
>>> def memoized(func):
... cache = {}
... def wrapper(*args):
... if not isinstance(args, collections.Hashable):
... # uncacheable. a list, for instance.
... # better to not cache than blow up.
... return func(*args)
... if args in cache:
... print 'get cached version{}'.format(args)
... return cache[args]
... else:
... print 'compute {}'.format(args)
... value = func(*args)
... cache[args] = value
... return value
... return wrapper
...
>>> @memoized
... def fibonacci(n):
... "Return the nth fibonacci number."
... if n in (0, 1):
... return n
... return fibonacci(n-1) + fibonacci(n-2)
...
>>> fibonacci.__closure__
(<cell at 0x1035ed590: dict object at 0x103606d70>, <cell at 0x1036002f0: function object at 0x1035fe9b0>)
>>> fibonacci.__closure__[1].cell_contents
<function fibonacci at 0x1035fe9b0>