0

我正在编写一个测试方法,比如说,test_foo(使用 pytest)。我正在测试一个函数的行为,该函数foo将另一个函数 . 作为参数getfoo迭代地调用get,有条件地根据 的返回值get,例如:

def foo(get, param):
    max_num_tries = 3
    curr_num_tries = 0
    response = get(param)
    while curr_num_tries < max_num_tries and response.status_code == BAD_STATUS_CODE:
        response = get(param)
    return response

我正在尝试覆盖get,以便它可以访问它被调用的次数,并可以相应地返回不同的值。

这是我到目前为止的简化版本:

def test_foo():
    tries_so_far = 0

    def get(arg1):
        global tries_so_far
        if tries_so_far < 3:
            tries_so_far += 1
            print("do something special here")
        else:
            print("do something else here")
        return "some return val"

    foo(get, "some arg")

但是,我收到以下错误:

NameError: global name 'tries_so_far' is not defined

如果我在模块级别定义tries_so_far之外,我会得到预期的行为。test_foo但是,我想tries_so_far成为一个本地变量test_foo

有没有办法让get读/写tries_so_far使用全局变量或其他技术?注意:我无法更改get.

4

1 回答 1

2

根据这个问题的公认答案为什么Python中的函数可以在封闭范围内打印变量但不能在赋值中使用它们?,在 Python 3 中添加了一个额外的语句:nonlocal这就是你想要的。就像global,但说要查看封闭范围而不是模块级别。因此,以下修改应该允许您完全按照您的意愿行事:

def test_foo():
    tries_so_far = 0

    def get(arg1):
        nonlocal tries_so_far
        if tries_so_far < 3:
            tries_so_far += 1
            print("do something special here")
        else:
            print("do something else here")
        return "some return val"

    foo(get, "some arg")

虽然您的问题与我上面引用的问题并不完全相同,但您应该阅读已接受的答案。它非常好,可能会解决您对该主题的许多未说明的问题。

于 2016-02-12T17:21:32.460 回答