哪种序列类型更适合比较,为什么? (Python)

Which sequence type is better for a comparison and why? (Python)

我有一个条件可以将一个对象与其他多个对象进行比较,如下所示:

if 'a' in ('a','b','c','e'):

序列是为此目的创建的,不存在于函数的其他任何地方。考虑到它们似乎工作相同且列表很短,将其分组为元组、列表或集合的优缺点是什么?哪个是地道的?

使用集合直到你有充分的理由不使用。(然后使用列表。)

我会认为集合更加地道。它传达的意思更清楚,因为顺序无关紧要,重要的是成员身份。

要明确一点,集合是 集合 但不是 "sequence type"(即使它是可迭代的),因为它在语义上是 "unordered"。


为什么不用一套?

集合只能包含 可散列 类型。而且,这很重要,当您询问集合中是否存在不可散列的类型时,他们将引发 TypeError 而不是简单地返回 False 。如果您可能在 in 运算符的两边都得到一个不可散列的对象,那您就不走运了。有时您可以使用可哈希元素代替(例如 frozenset 而不是 settuple 而不是 list),有时您不能。

但是元组和列表不必对它们的元素进行哈希处理。


为什么在元组上使用列表?

列表的主要优点是它们避免了一个元素的元组的句法怪癖。假设您有 ('foo', 'bar'),后来决定删除 'bar'。那么你有('foo')。哎呀,看到我在那里做了什么吗?它实际上应该是 ('foo',)。很容易忘记逗号。 in 检查仍然适用于像 ('foo') 这样的字符串,因为 in 检查子字符串。这可以巧妙地改变程序的含义。 'oo'('foo') 中,但不在 ('foo',) 中。

['foo'] 这样的单项列表没有这个问题。 [并作为 user2357112 指出,一个常量列表无论如何都会被编译成一个元组。]

请注意,像 {'a'} 这样的单项集也不存在该问题。一个空的 {} 是一个字典,但这不会导致 in 检查出现任何问题,因为它也是一个空集合。

但是当仅与一个元素进行比较时,可以说您应该使用 == 而不是 in


为了清楚起见,就这些了。现在进行微优化。早期优化是万恶之源。在实际需要之前,不要以牺牲可读性为代价进行优化。

集合查找如果不是太小则速度更快,因为必须逐个检查元组的元素(平均而言)随着元组的大小而增长,而集合​​由哈希表支持(就像一个字典),它有一个小的恒定开销。如果事例的分布不均匀,这意味着元组中元素的顺序很重要。平均而言,将更常见的情况放在元组的前面将使检查速度比反向快得多。

要使集合的恒定开销很重要,集合必须多小?配置文件并查看。性能可能因许多因素而异。这不仅仅是元素的数量,还包括相等性检查需要多长时间,以及它们在内存中的位置等。

与其他集合相比,元组在内存和构造时间方面的开销应该略小。但是,如果编译器可以将其加载为保存的常量值,那么构造开销并不重要。 (当所有元素本身在编译时都是常量时,就会发生这种情况。您可以使用 dis 模块来确认这种情况。)