0

我想获取 Python 函数的源代码。但是,我正在处理的函数具有使用函数本身实例化的装饰器。这似乎inspectdill有问题。特别是,我尝试了以下 MWE:

class Decorator(object):
    def __init__(self, item):
        self.item = item
        self.func = None
    def __call__(self, func):
        self.func = func
        return self

@Decorator(42)
def fun_1():
    pass

@Decorator(lambda x: 42)
def fun_2():
    pass

@Decorator(fun_2.item)
def fun_3():
    pass

import inspect
print("Inspect results")
print(inspect.getsource(fun_1.func))
print(inspect.getsource(fun_2.func))
print(inspect.getsource(fun_3.func))

import dill
print("Dill results")
print(dill.source.getsource(fun_1.func))
print(dill.source.getsource(fun_2.func))
print(dill.source.getsource(fun_3.func))

对于函数fun_1fun_3,这给出了预期的结果。对于fun_2(虽然它本质上与 fun_3 相同),inspector返回的源代码dill是错误的——它只给了我装饰器行。我希望得到

@Decorator(lambda x: 42)
def fun_2():
    pass

但我得到的只是

@Decorator(lambda x: 42)

我可以想象这两个模块都只是搜索第一个函数声明。inspect这个假设是否正确,除了重新实现或之外是否有很好的解决方法dill

编辑:我使用的是 Python 2.7,但使用 Python 3.4 时遇到了相同的行为。

4

1 回答 1

2

我是dill作者。我认为您在 中发现了一个inspect关于解析包含 alambda作为装饰器中的参数的代码块的错误。

>>> f = lambda x: 42
>>> @Decorator(f)
... def fun_4():
...     pass
... 
>>> 
>>> print dill.source.getsource(fun_4.func)
@Decorator(f)
def fun_4():
    pass

>>>

请注意,当您仅使用指向lambda对象的指针时,上述方法有效。所以这就是你的解决方法。

我相信这个角落案例是一个错误inspect,它dill在幕后使用......所以它也是一个错误dill

我在 GitHub 页面上打开了一张票,我dill将进一步调查它以查看 (1) 是否有可以dillinspect是)——如果是这样,它应该填充给 python 开发人员。这是票的链接:https ://github.com/uqfoundation/dill/issues/221

于 2017-03-29T15:42:02.957 回答