gpt4 book ai didi

python - 在函数中将闭包传递给 FunctionType

转载 作者:行者123 更新时间:2023-11-28 21:17:50 25 4
gpt4 key购买 nike

我有这样的代码:

class A():
def __init__(self, a):
self.a = a

def outer_method(self):
def inner_method():
return self.a +1
return inner_method()

我想为 inner_method 编写测试。为此,我使用了这样的代码:

def find_nested_func(parent, child_name):
"""
Return the function named <child_name> that is defined inside
a <parent> function
Returns None if nonexistent
"""
consts = parent.__code__.co_consts
item = list(filter(lambda x:isinstance(x, CodeType) and x.co_name==child_name, consts ))[0]
return FunctionType(item, globals())

使用 find_nested_func(A().outer_method, 'inner_method') 调用它,但在调用 'FunctionType' 时失败,因为无法创建函数,因为 'self.a' 不再存在于函数不再是内部函数的时刻。我知道构造 FunctionType 可以接收一个可以解决此问题的闭包作为参数,但我不知道如何使用它。我怎样才能通过它?

它给出的错误是下一个:

    return FunctionType(item, globals())
TypeError: arg 5 (closure) must be tuple

最佳答案

为什么要测试 inner_method?在大多数情况下,您应该只测试公共(public) API 的一部分。 outer_methodA 的公共(public) API 的一部分,所以只测试它。 inner_method 是一个可以更改的实现细节:如果您决定重命名它怎么办?如果您在不修改 outer_method 的外部可见行为的情况下稍微重构它会怎样? A 类的用户无法(轻松)调用 inner_method。单元测试通常只用于测试您类(class)的用户可以调用的东西(我假设这些是用于单元测试的,因为这种粒度的集成测试会很奇怪——同样的原则仍然大部分成立)。

实际上,提取在另一个函数范围内定义的函数时会遇到问题,原因有多种,包括变量捕获。您无法知道 inner_method 是否仅捕获 selfouter_method 是否执行一些逻辑并计算一些变量 inner_method 使用。例如:

class A:
def outer_method():
b = 1

def inner_method():
return self.a + b

return inner_method()

此外,您可以在函数定义周围使用控制语句,因此如果不运行 outer_method 就无法决定使用哪个定义。例如:

import random

class A:
def outer_method():
if random.random() < 0.5:
def inner_method():
return self.a + 1
else:
def inner_method():
return self.a + 2

return inner_method()

您不能在此处提取 inner_method,因为它们有两个,并且在运行 outer_method 之前您不知道实际使用了哪个。

所以,不要测试 inner_method

如果 inner_method 真的足够复杂以至于您想单独测试它(如果您这样做,原则性测试说您应该模拟它的用途,例如它在 outer_method 中的使用),然后将其设为 A 上的“private-ish”方法:

class A:
def _inner_method(self):
return self.a + 1
def outer_method(self):
return self._inner_method()

有原则的测试说你真的不应该测试下划线方法,但有时需要这样做。这样做可以让您像测试任何其他方法一样测试 _inner_method。然后,在测试 outer_method 时,您可以通过执行 a._inner_method = Mock() 来模拟它(其中 aA 被测对象)。

此外,使用 A 类。 parens 是不必要的,除非你有父类。

关于python - 在函数中将闭包传递给 FunctionType,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/55282608/

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