【发布时间】:2015-09-13 17:14:07
【问题描述】:
我正在考虑制作一个装饰器以提高性能。一个装饰器,它修改它所装饰的函数的源代码,并返回修改后的函数。
在思考这个问题时,我想如果我能得到函数的源代码,我就可以做到这一点。但是是否可以在装饰器中访问函数的源代码?如果我有这样的装饰器:
import inspect
def decorate(f):
exec(inspect.getsource(f))
return eval(f.__name__)
@decorate
def test():
return 1
我得到一个 OSError:
OSError: could not get source code
这似乎是因为test 在传递到decorate 之前尚未完全形成。但是,这是可行的:
import inspect
def decorate(f):
exec(inspect.getsource(f))
return eval(f.__name__)
def test():
return 1
test = decorate(test)
不过,它只是没有那种装饰风格。这似乎是可能的,因为f.__code__ 已定义。
经过进一步检查,似乎只有当我将inspect.getsource(f) 放入exec 时才会发生这种情况。不然的话,好像能拿到源码了。
作为我想到的第一件事的粗略草图,我正在考虑尾递归。不幸的是,我编写了这个装饰器,它很慢,并且需要非常特定的样式来编写要装饰的函数:
def tail_recurse(acc_default):
def decorate(f):
def wrapper(*args, acc=acc_default):
args = args + (acc,)
while True:
return_type, *rargs = f(*args)
if return_type is None:
return rargs[-1]
args = rargs
return wrapper
return decorate
基本上,我正在考虑做一些简单的事情,比如将函数的主体替换为:
while True:
__body__
update_args
【问题讨论】:
-
ast 可能更适合你想要的东西
-
在
exec(inspect.getsource(f))之前留一行空,它会起作用。有趣!! -
@AshwiniChaudhary 这对我没有任何作用......但这让我认为这可能是一个并发问题,或者依赖于实现
-
@Quincunx 我在 IPython shell 中使用 %run 进行了不同的测试。使用普通的 python 命令它不起作用。
-
@Quincunx,你打算如何修改源代码?
标签: python function decorator python-decorators