[英]getting a python function of functionType for a nested function with recursion
我正在尝试对嵌套函数(函数内的函数)进行单元测试,我正在使用来自以下链接的代码(“嵌套”是函数名称),它将提供闭包并返回一个可从测试中调用的有效函数。 它适用于简单的功能。 我试图让它适用于递归函数。
例如:我试图为“innerfunction”获取一个有效的函数,它在 co_freevars 中有一个条目为“innerfunction”。
我想为“内部函数”获取一个函数(我相信是 FunctionType)作为可调用的。 为了得到这个,我需要用一个带有“内部函数”的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 = 嵌套(顶层函数,'内部函数')
功能(5)
将返回错误需要一个长度为 1 的闭包。添加一个引用“const”的闭包表明它是 CodeType 而不是 FunctionType。 在阅读完文档后,添加一个闭包值来引用自身似乎很棘手。
我确实发现内部函数为:
{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
是内部函数中使用的标识符,您必须指定内部函数中使用的每个标识符的值。 可调用标识符也不例外:
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()
配方的扩展自动执行此操作将是更好的方法。 随意分叉配方并添加这个方面! :-)
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.