我想看看一个带修饰符的修饰函数的字节码。你知道吗
例如,在下面的示例中,fibonacci由memoized修饰。但是当我打电话给dis.dis公司在fibonacci上,这将显示实际函数的字节码。你知道吗
我想能够看到,如果一个函数已经装饰,并看到字节码包括装饰部分。你知道吗
我完全误解了什么概念吗?你知道吗
import collections
import functools
class memoized(object):
'''Decorator. Caches a function's return value each time it is called.
If called later with the same arguments, the cached value is returned
(not reevaluated).
'''
def __init__(self, func):
self.func = func
self.cache = {}
def __call__(self, *args):
if not isinstance(args, collections.Hashable):
# uncacheable. a list, for instance.
# better to not cache than blow up.
return self.func(*args)
if args in self.cache:
print 'get cached version{}'.format(args)
return self.cache[args]
else:
print 'compute {}'.format(args)
value = self.func(*args)
self.cache[args] = value
return value
def __repr__(self):
'''Return the function's docstring.'''
return self.func.__doc__
def __get__(self, obj, objtype):
'''Support instance methods.'''
return functools.partial(self.__call__, obj)
@memoized
def fibonacci(n):
"Return the nth fibonacci number."
if n in (0, 1):
return n
return fibonacci(n-1) + fibonacci(n-2)
print fibonacci(12)
import dis
f = fibonacci
dis.dis(f)
在实例上调用
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__)
为反汇编程序提供对未绑定或绑定方法的引用。你知道吗由于decorating是语法糖,用于用传入的函数调用另一个对象,然后用结果替换该函数,因此不存在decoratior与原始函数一起反汇编的情况。最好的方法是分别分解decorator可调用函数和原始函数:
您可以从
fibonacci.__call__
反汇编中看到,它将调用self.func()
(字节码18到27),这就是为什么您要查看fibonacci.func
。你知道吗对于使用闭包的函数装饰器,您必须通过查看
__closure__
对象深入包装闭包以提取原始函数:相关问题 更多 >
编程相关推荐