哪种序列类型比较好?为什么?(Python)

哪种序列类型比较好?为什么?(Python),python,types,comparison,sequence,Python,Types,Comparison,Sequence,我有一个条件,将一个对象与其他几个对象进行比较,如下所示: 如果'a'中的'a'('a'、'b'、'c'、'e'): 该序列是为此目的创建的,在函数的其他任何位置都不存在。考虑到它们的工作原理相同,而且列表很短,将其分组为元组、列表或集合的利弊是什么?哪一个是惯用的?使用集合,直到你有充分的理由不这样做。(然后使用列表。) 我认为一套更符合习惯。它更清楚地表达了意思,因为秩序不重要,只有成员资格才重要 更清楚的是,集合是一个集合,但不是“序列类型”(即使它是iterable),因为它在语义上是

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

如果'a'中的'a'('a'、'b'、'c'、'e'):
该序列是为此目的创建的,在函数的其他任何位置都不存在。考虑到它们的工作原理相同,而且列表很短,将其分组为元组、列表或集合的利弊是什么?哪一个是惯用的?

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

我认为一套更符合习惯。它更清楚地表达了意思,因为秩序不重要,只有成员资格才重要

更清楚的是,集合是一个集合,但不是“序列类型”(即使它是iterable),因为它在语义上是“无序的”


为什么不用一套呢

集合只能包含哈希类型。而且,这一点很重要,当您询问集合中是否存在不可损坏的类型时,他们将引发
TypeError
,而不是简单地返回
False
。如果在操作符中,
的两侧都有一个不可损坏的对象,那么您就倒霉了。有时可以使用散列元素(例如
frozenset
而不是
set
tuple
而不是
list
),有时则不能

但是元组和列表不必散列它们的元素


为什么是一个列表而不是一个元组

列表的主要优点是它们避免了一个元素的元组的语法怪癖。假设您有
('foo','bar')
,然后决定删除
'bar'
。然后就是
('foo')
。哦,看到我在那里做了什么吗?它实际上应该是
('foo',)
。很容易忘记逗号。而且
中的
检查仍然适用于类似
('foo')
的字符串,因为
中的
检查子字符串。这会微妙地改变程序的含义<代码>'oo'
('foo')
中,但不在
('foo',)

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

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

但是,当只与一个元素进行比较时,可以证明您应该使用
==
而不是
中的


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

如果集合不太小,则查找速度更快,因为必须逐个检查元组的元素,这些元素(平均)随元组的大小而增长,而集合由哈希表(如dict)支持,哈希表具有较小的恒定开销。如果事例的分布不均匀,这意味着元组中元素的顺序非常重要。平均而言,将更常见的情况放在元组的第一位将使检查速度比相反的快得多

集合必须有多小才能使集合的恒定开销发挥作用?配置文件,请参见。性能可能因许多因素而有所不同。这不仅仅是元素的数量,而是平等性检查需要多长时间,以及它们在内存中的位置等等


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

如果您只有四个元组值,则对于较大的数量,请使用set,您可以定义一个set-literal,如
{'a','b','c','e}
。那
是_foo
用函数调用开销来交换集合创建开销。在这个微优化级别上,函数调用开销很重要。(此外,CPython还有一个优化功能,可以为{'set','of','constants'}
表达式中的
对象预先构造并保存一个冻结集。)(该优化功能还为['list','of','constants']
中的
对象预先构造并保存一个元组,并将其保存在('set','of','constants')
中)@用户2357112使用
dis
,以及是的,frozenset或元组常量,至少在CPython 3.7中进行了尝试。我不知道那个优化。你能详细说明一下函数调用开销吗?当然,与完全没有函数相比,我认为它是在一个函数中。有默认参数的函数会比没有默认参数的函数更糟糕吗?我将把
Is_foo(x)
与{'a','b','c','e'}
中的
x进行比较,而不是与另一个函数调用进行比较。当然,{'a','b','c','e'}
检查可能在某个函数中,但我认为,尝试应用此答案中的建议的人更可能直接用
is\u stuff(x)
调用替换
x in(bunch,of,stuff)
检查,而不是向现有函数添加
\u stuff\u set
默认参数并在
x in\u stuff\u set
。(另外,向现有函数添加默认参数会增加默认参数隐藏错误的可能性。)