哪种序列类型比较好?为什么?(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
。(另外,向现有函数添加默认参数会增加默认参数隐藏错误的可能性。)