我不完全理解这个脚本中的 any() 函数是如何工作的

I don't fully understand how the any() function in this script works

我有一个脚本可以检查列表中是否有一个或多个相同的项目。这是代码:

items = ["Blue", "Black", "Red"]

def isUnique(item):
    seen = list()
    return not any(i in seen or seen.append(i) for i in item)


print(isUnique(items))

如果给定列表中的所有项目都是唯一的,则打印“True”;如果列表中的一个或多个项目是唯一的,则打印“False”。有人可以为我解释脚本的 any() 部分吗,因为我不完全理解它是如何工作的?

很简单:any()里面的表达式是一个generatorany() 从那个生成器中提取,returns True(和 stops)在生成器的第一个元素 True 处。如果它耗尽了发电机,那么它 returns False.

生成器中的表达式 (i in seen or seen.append(i)) 是一种将以下逻辑表达为一行的技巧:如果 i 在列表中,则表达式为 True并且 any() 立即停止,否则,i 被添加到列表中并且生成器继续。

使用 set 代替 list 可以显着改善功能:

def isUnique(item):
    seen = set()
    return not any(i in seen or seen.add(i) for i in item)

set (O[1]) 中测试项目是否存在比在 list (O[n]) 中测试要快得多。

此代码的一个有趣且可能未被充分认识的方面是它适用于(可能是无限的)生成器。它将停止 在第一个重复项处从生成器中绘制。生成器将获得的后续项目根本不会被评估(具有潜在的副作用,无论是否合意)。

适用于已知和有限项目集合的不同方法如下:

def isUnique(items):
    items = tuple(items)  # in case items is a generator
    return len(set(items)) == len(items)

这假设所有项目都适合内存。显然,如果 items 是一个非常大或无限数量的元素的生成器,这将不起作用。

这段代码有点像 hack,因为它使用了带有副作用的生成器表达式,并利用了 append returns None 的事实,这是错误的。

命令式风格的等效代码如下:

def isUnique(items):
    seen = list()
    for i in items:
        if i in seen or seen.append(i):
            return False
    return True

那里的or还是有点奇怪——它被用于它的short-circuiting behaviour,所以append只在i in seen为false时被调用——所以我们可以这样重写它:

def isUnique(items):
    seen = list()
    for i in items:
        if i in seen:
            return False
        else:
            seen.append(i)
    return True

这是等价的,因为 append 仅在 i in seen 为假时调用,而对 append returns None 的调用意味着 return False 行不应在这种情况下执行。

编辑:有很好的答案。添加一些更简单的方法来实现想要的结果:

方法一:

items = ["Blue", "Black", "Red"]
items_set = set(items)
if len(items_set) != len(items):
    # there are duplications

之所以有效,是因为集合对象“删除”了重复项。

方法二:

contains_duplicates = any(items.count(element) > 1 for element in items) # true if contains duplications and false otherwise.

https://www.kite.com/python/answers/how-to-check-for-duplicates-in-a-list-in-python ————————————————

any 是个很棒的函数

Return True if any element of the iterable is true. If the iterable is empty, return False

但是,您的函数 isUnique 的逻辑要多一些。让我们分解一下:

首先创建一个空列表对象并将其存储在 'seen' 变量中。

for i in item - 迭代项目列表。

i in seen - 如果 'i' 是 'seen' 的成员,则此语句 return 为真,否则为假。

seen.append(i) - 将 i 添加到 seen 中。这条语句 returns None if 'i' appened seen successfully.

注意 i in seen or seen.append(i) 之间的 or 语句。这意味着,如果此处的陈述之一为 True,则 or 陈述 returns 为 True。

此时,我会 运行 [i in seen or seen.append(i) for i in item],查看结果并进行试验。您的示例的结果是 [None, None, None].

基本上,对于每个项目,您都将其添加到列表中并检查它是否已经在列表中。

最后,您使用 any() 函数 - 如果可迭代对象具有 True 值,则该函数 return 为真。只有当 i in seen 将 return 为真时才会发生这种情况。

注意您正在使用 not any(...),如果没有重复,returns False。

有更简单、更清晰的方法来实现这一点。你应该试试!

这里需要先了解一下or运算符的工作原理。 或者像 exp1 or exp2

它只计算先给出True或最后给出True的表达式

例如

>>> 2 or 3
2
>>> 5 or 0.0
5
>>> [] or 3
3
>>> 0 or {}
{}

现在为了您的列表理解,[i in seen or seen.append(i) for i in items] i in seen 评估 false 和 seen.append(i) True 以及 return Nonelist.append return None 所以,理解包含所有 None

>>> seen = []
>>> items = ["Blue", "Black", "Red"]
>>> res = [i in seen or seen.append(i) for i in items]
>>> res
[None, None, None]
>>> any(res)
False

根据 any 文档,它是 returning false 因为它不是可迭代的或 bool。

>>> help(any)
Help on built-in function any in module builtins:

any(iterable, /)
    Return True if bool(x) is True for any x in the iterable.

    If the iterable is empty, return False.

python 中的 any 函数采用布尔值列表,return 是所有布尔值的 OR。

i in seen or seen.append(i) for i in itemi 附加到 seen(如果它不在 seen 中)。但是如果它已经被看到那么 append() 不会 运行 因为第一部分已经是 True,并且 python 不需要知道第二部分是否为真因为 True OR'd任何事情都是真的。所以它不执行它。所以 seen 数组最终成为它所见过的唯一颜色列表。

i in seen or seen.append(i) for i in item 也是一个生成器表达式, 它生成布尔值,any 检查它生成的布尔值,即使其中一个计算结果为真,整个 any 也会 return 真。

所以第一次找到已经在 seen 数组中的项目时,any 将停止生成器并且 return True 本身。

因此,如果重复元素恰好在数组中,则不会评估更多条件,也不会向 seen 数组追加更多元素

所以如果数组有重复的元素,比如,

items = ["Blue", "Blue", "Black", "Red"]


def isUnique(item):
    seen = list()
    unique = not any(i in seen or seen.append(i) for i in item)
    print(seen)
    return unique


isUnique(items)

将导致输出,只是 ['Blue']