Map函数好像没有执行?

Nat*_*ord 1 python-3.x

我正在尝试为使用简单验证函数的函数编写测试。我的函数需要验证所有传入的参数。验证函数AttributeError在出现问题时抛出一个,否则返回 True。但是,当我映射时validate它不起作用,除非我做一些额外的事情,比如使用all()

def my_function(a, b, c=None):
    map(validate, (a, b, c))  # This doesn't fail validation (incorrect behavior)
    all(map(validate, (a, b, c))  # This DOES fail validation (correct behavior)
    # Some other stuff
Run Code Online (Sandbox Code Playgroud)

我的单元测试是这样做的:

def test_my_function(self):
    bad_id = 0
    self.assertRaises(AttributeError, add_favorite, 10, bad_id)
Run Code Online (Sandbox Code Playgroud)

这是我的验证功能:

def validate(identifier):
    if identifier is None:
        return True
    elif not isinstance(identifier, int):
        raise AttributeError("Identifier={0} not of type integer.".format(identifier))
    elif not (identifier > 0):
        raise AttributeError("Identifier={0} not an integer greater than zero.".format(identifier))
    else:
        return True
Run Code Online (Sandbox Code Playgroud)

我很困惑为什么map除非我将它包装在其他东西中,否则为什么似乎不会执行:我已经通过调试运行测试并看到它从未进入validate(). (我认为做额外的工作没有意义......)根据文档,似乎 map应该迭代这些参数并执行该函数。有人可以解释为什么没有吗?

编辑:正确的文档显示 map 返回一个延迟评估的迭代器。

The*_*Cat 5

在 python 3.x 中,map创建一个可迭代对象。Iterables 是惰性求值的——也就是说,只有你迭代的元素(例如循环它们)才会被实际求值。在您的示例中,由于您没有迭代任何值,因此不会对任何值进行评估。any然而,在这种情况下,any迭代整个 result map,所以整个事情都会得到评估。

它有点复杂,因为还有其他方法可以在不迭代的情况下评估可迭代的部分(例如next()用于评估并获取下一项),但对于您的目的来说,这已经足够了。

所以这些得到评估:

all(map(validate, (a, b, c))
list(map(validate, (a, b, c)))
[_ for x in map(validate, (a, b, c))]
a = map(validate, (a, b, c);all(a)
b = map(validate, (a, b, c));list(b)
Run Code Online (Sandbox Code Playgroud)

请注意,在最后两种情况下,直到调用all(a)or 时才会评估可迭代对象list(a)。这可能是代码后面、另一个函数和/或另一个模块中的许多行。

此外,iterable 一次只计算一个步骤。考虑这个例子:

for x in map(validate, (a, b, c)):
    print(x)
Run Code Online (Sandbox Code Playgroud)

它将validate在第一项上运行,放入 x 中,然后在循环体中运行。一旦循环的第一次运行完成,它才会评估第二项,然后再次运行循环体,然后评估下一项,依此类推。如果您打破循环,则不会评估其余项目。

这些没有得到评估:

map(validate, (a, b, c)
a = map(validate, (a, b, c)
(_ for x in map(validate, (a, b, c)))
Run Code Online (Sandbox Code Playgroud)