gpt4 book ai didi

python - 为具有递归的嵌套函数获取 functionType 的 python 函数

转载 作者:太空宇宙 更新时间:2023-11-04 05:15:31 27 4
gpt4 key购买 nike

我正在尝试对嵌套函数(函数内部的函数)进行单元测试,我正在使用下面链接中的代码(“嵌套”是函数名称),它将提供闭包并返回可从测试中调用的有效函数。它适用于简单的功能。我试图让它适用于递归函数。

举个例子:我正在尝试获取“innerfunction”的有效函数,它在 co_freevars 中有一个条目作为“innerfunction”。

我想为“innerfunction”获取一个函数(我相信是 FunctionType)作为可调用函数。为此,我需要使用带有“innerfunction”的 FunctionType 的元组来调用 FunctionType。这成为递归的“依赖”。我如何解决为“闭包”发送的参数的这种依赖性

功能

def toplevelfunction():
def innerfunction(a):
print ('val of a is ', a)
if a > 0:
innerfunction(a -1)
innerfunction(10)

我使用的原始代码:

def freeVar(val):
def nested():
return val
return nested.__closure__[0]

codeAttribute = '__code__' if sys.version_info[0] == 3 else 'func_code'

def nested(outer, innerName, **freeVars):
if isinstance(outer, (types.FunctionType, types.MethodType)):
outer = outer.__getattribute__(codeAttribute)
for const in outer.co_consts:
if isinstance(const, types.CodeType) and const.co_name == innerName:
return types.FunctionType(const, globals(), None, None, tuple(
freeVar(freeVars[name]) for name in const.co_freevars))

https://code.activestate.com/recipes/580716-unit-testing-nested-functions/

如何添加对闭包的支持,如下所示:

func = nested(toplevelfunction, 'innerfunction')

函数(5)

会返回错误,需要一个长度为 1 的闭包。添加引用“const”的闭包显示它是 CodeType 而不是 FunctionType。阅读文档后,添加闭包值来引用自身似乎很棘手。

我发现 innerfunction 是:

 {code} <code object innerfunction at 0x104b9bc00, file "/<filedirectory>/handle_results.py", line 44>
co_argcount = {int} 1
co_cellvars = {tuple} <class 'tuple'>: ()
co_code = {bytes} b"t\x00\x00d\x01\x00|\x00\x00\x83\x02\x00\x01|\x00\x00d\x02\x00k\x04\x00r'\x00\x88\x00\x00|\x00\x00d\x03\x00\x18\x83\x01\x00\x01d\x00\x00S"
co_consts = {tuple} <class 'tuple'>: (None, 'val of a is ', 0, 1)
co_filename = {str} '/<fildirectory>/handle_results.py'
co_firstlineno = {int} 44
co_flags = {int} 19
co_freevars = {tuple} <class 'tuple'>: ('innerfunction ',)
co_kwonlyargcount = {int} 0
co_lnotab = {bytes} b'\x00\x01\r\x01\x0c\x01'
co_name = {str} 'innerfunction '
co_names = {tuple} <class 'tuple'>: ('print',)
co_nlocals = {int} 1
co_stacksize = {int} 3
co_varnames = {tuple} <class 'tuple'>: ('a',)

最佳答案

感谢您就您在问题中链接到的我的 ActiveState 配方的这一限制向我暗示!

您尝试对局部递归函数进行单元测试;我的最小示例如下所示:

def f(x):
def fac(n):
return fac(n-1) * n if n > 1 else 1
print "Faculty of", x, "is", fac(x)

所以在单元测试中你想测试内部函数fac()。简单地应用我的食谱会导致此错误:

nestedFac = nested(f, 'fac')
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
File "<stdin>", line 7, in nested
File "<stdin>", line 7, in <genexpr>
KeyError: 'fac'

这是因为 fac 是内部函数中使用的标识符,您必须指定内部函数中使用的每个标识符的值功能。可调用标识符也不异常(exception):

nestedFac = nested(f, 'fac', fac=None)

这会将 fac 设置为值 None 并且对 nested 的调用不会再失败。

不幸的是,生成的函数将在您调用它时尝试调用 None(...):

nestedFac(5)
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
File "<stdin>", line 3, in fac
TypeError: 'NoneType' object is not callable

您需要将函数本身作为 fac 的值传递以避免这种情况。不幸的是,当您调用 nested() 时您还没有它。可以像这样重复包装:

nestedFac = nested(f, 'fac', fac=None)
nestedFac = nested(f, 'fac', fac=nestedFac)
nestedFac = nested(f, 'fac', fac=nestedFac)
nestedFac = nested(f, 'fac', fac=nestedFac)

这会将您的递归深度限制为您应用的环绕次数:

nestedFac(2)
2
nestedFac(3)
6
nestedFac(4)
24
nestedFac(5)
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
File "<stdin>", line 3, in fac
File "<stdin>", line 3, in fac
File "<stdin>", line 3, in fac
File "<stdin>", line 3, in fac
TypeError: 'NoneType' object is not callable

为避免这种情况,您可以传递一个本地函数作为代理:

def q(*args, **kwargs):
return nestedFac(*args, **kwargs)
nestedFac = nested(f, 'fac', fac=q)

或者作为 lambda:

nestedFac = nested(f, 'fac', fac=lambda *args, **kwargs:
nestedFac(*args, **kwargs))

或者对于只有一个参数的特殊情况:

nestedFac = nested(f, 'fac', fac=lambda n: nestedFac(n))

nested() 自动执行此操作的扩展将是更好的方法。随意 fork 食谱并添加这方面! :-)

关于python - 为具有递归的嵌套函数获取 functionType 的 python 函数,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/41814589/

27 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com