当 Iterable 中只有一项时,为什么 `min()` 会调用关键函数?

问题描述 投票:0回答:1

似乎Python内置函数

min()
调用 指定的按键功能,即使只剩下一项:

foo = ['2']
def key_func(value):
    print("Key function called")
    return int(value)
print(min(foo, key=key_func))

给出:

Key function called
2

同样的观察也适用于

max()
sorted()

为什么

len(iterable) == 1
没有快捷方式? 想象一下当
key_func
进行昂贵的计算时的情况 那就没有用了。

我阅读了 Python 文档,但没有找到对此行为的解释,但我认为一定有一个解释,因为众所周知,Python 核心开发团队在定义和证明语言和标准库的行为时非常严格。

python sorting
1个回答
3
投票

您必须选择其中之一,不能同时拥有:

  • 保证每个项目
    key
    始终按照可迭代中项目的原始顺序被调用一次;
  • 避免对仅包含一项的可迭代项调用
    key

这两个约定中的一个优于另一个并不明显,调用

min
sorted
并关心第二个约定的程序员可以在自己的代码中添加一个规定来实现这一效果,并且当可迭代对象只有一项时,根本不调用
sorted

请注意,并非所有可迭代对象都是像

list
tuple
这样的序列;一些迭代不支持
len
,因此在调用
key
之前检查它们是否有一个或多个项目的唯一方法是获取第一个项目,尝试获取第二个项目,并且仅当
StopIteration
尝试获取第二个项目时未引发,然后对第一个项目调用
key

想象一下当 key_func 进行昂贵的计算但没有用处的情况。

这是可能的,但可能不是关键功能的绝大多数用例;在许多情况下,关键只是

operator.itemgetter(...)
lambda x: x[1].upper()
或类似的东西。如果 key_func 执行昂贵的计算,您可能不想使用
key=key_func
,它会在工作完成后立即丢弃结果;您可能希望保留计算结果,以避免下次需要时重新计算。

当 key_func 进行昂贵的计算时,您提出的优化很好,但用户可以通过在调用

sorted
min
之前检查项目数量来显式完成;当 key_func 不进行昂贵的计算时(这可能是大多数情况),您提出的优化将比仅无条件调用 key 函数更昂贵。

© www.soinside.com 2019 - 2024. All rights reserved.