Why does Python treat tuples, lists, sets and dictionaries as fundamentally different things?
我喜欢Python的原因之一是元组、列表、集合和字典提供的表达能力/减少的编程工作量。一旦你理解了清单的理解和一些基本模式的使用和为,生活会变得更好!Python摇滚。
然而,我想知道为什么这些构造被视为与它们不同,以及随着时间的推移这是如何变化的(变得越来越陌生)。回到python 2.x,我可以提出这样一个论点:它们都是基本集合类型的变体,有些非异国情调的用例要求您将字典转换为列表,然后再转换回来,这有点令人恼火。(字典不只是具有特定唯一性约束的元组列表吗?列表是否只是一个具有不同类型唯一性约束的集合?).
现在在3.x的世界里,情况变得更复杂了。现在有了命名的元组——开始感觉更像是一个特殊情况字典。现在有了有序的字典——开始觉得更像是一个列表。我刚看到一份定做套装的食谱。我可以想象这种情况不断发生…唯一的列表等如何?
python的禅宗说"应该有一种——最好只有一种——显而易见的方法"。在我看来,这种丰富的专门集合类型与这个Python规则相冲突。
硬核的Python派怎么想?
这些数据类型都有不同的用途,在理想的环境中,您可能能够更统一它们。然而,在现实世界中,我们需要对基本集合进行有效的实现,例如,排序会增加运行时惩罚。
命名的元组主要用于使stat()等的接口更可用,并且在处理SQL行集时也很好。
您要寻找的大统一实际上是以不同的访问协议(getitem、getattr、iter,…)的形式存在的,这些类型根据其预期目的混合和匹配。
tl;dr(鸭子打字)
在所有这些数据结构中看到一些相似之处是正确的。记住,Python使用鸭子打字(如果它看起来像鸭子,嘎嘎叫起来像鸭子,那么它就是鸭子)。如果您可以在相同的情况下使用两个对象,那么为了您当前的目的和目的,它们也可能是相同的数据类型。但是你必须时刻记住,如果你试图在其他情况下使用它们,它们可能不再以同样的方式工作。好的。
考虑到这一点,我们应该看看您提到的四种数据类型的实际差异和相同之处,以大致了解它们可以互换的情况。好的。易变性(你能改变它吗?)
您可以更改字典、列表和集合。如果不复制元组,就不能"更改"。好的。
可变:
dict 、list 、set 。好的。不变:
tuple 。好的。
python
Immutable objects can be optimized a lot
Ok.
In Python, only immutables are hashable (and only hashable objects can be members of sets, or keys in dictionaries).
Ok.
号
通过比较这个属性,列表和元组看起来像是"最近"的两种数据类型。在高层,元组是列表的不可变"冻结帧"版本。这使得列表对于将随时间变化的数据集很有用(因为您不必复制列表来修改它),但元组对于字典键(必须是不可变类型)之类的东西很有用。好的。排序(以及关于抽象数据类型的注释)
字典和集合一样,没有固有的概念顺序。这与列表和元组形成了对比,它们确实有顺序。口述或集合中的项目顺序是从程序员那里抽象出来的,这意味着如果元素a在
订单保存:
list 、tuple 。好的。非订单保存:
dict 、set 。好的。
从技术上讲,如果您连续两次迭代
每个元素一个"项目":
set 、list 、tuple 。好的。每个元素有两个"项目":
dict 。好的。
我想在这里您可以看到一个命名的元组,它对每个元素都有一个名称和一个值,就像一个不可变的字典。但这是一个微不足道的比较——请记住,如果您试图对一个命名的元组使用仅限字典的方法,那么duck类型会导致问题,反之亦然。好的。直接回答你的问题
Isn't a dictionary just a list of tuples with a particular uniqueness
constraint?Ok.
号
不,有几个不同之处。字典没有固有的顺序,这与列表不同,它有。好的。
此外,字典对每个"元素"都有一个键和一个值。另一方面,元组可以有任意数量的元素,但每个元素只能有一个值。好的。
由于字典的机制,其中键的作用类似于一个集合,所以如果您有键,可以在固定时间内查找值。在一个元组列表(这里是成对的)中,您需要遍历该列表直到找到键,这意味着搜索将在列表中元素的数量上是线性的。好的。
最重要的是,字典项可以更改,而元组不能更改。好的。
Isn't a list just a set with a different kind of uniqueness
constraint?Ok.
号
再次强调,集合没有固有的顺序,而列表有。这使得列表对于表示堆栈和队列之类的东西更有用,因为您希望能够记住附加项的顺序。SETS不提供这样的保证。然而,它们提供了能够在恒定时间内进行成员查找的优势,而列表也需要线性时间。好的。
There are now named tuples -- starting to feel more like a special-case dictionary. There are now ordered dictionaries -- starting to feel more like a list. And I just saw a recipe for ordered sets. I can picture this going on and on ... what about unique lists, etc.
Ok.
号
在某种程度上,我同意你的看法。然而,数据结构库对于支持已经很好建立的数据结构的常见用例是有用的。这使得程序员不必浪费时间来尝试对标准结构进行自定义扩展。只要它不失控,而且我们仍然可以看到每个解决方案的独特效用,在架子上放一个轮子是很好的,所以我们不需要重新发明它。好的。
一个很好的例子是counter()类。这本专门的词典对我来说已经用了好多次了(badoom tshhhhh!)它节省了我编写自定义解决方案的工作。我更愿意有一个社区帮助我开发和保持适当的Python最佳实践的解决方案,而不是我的自定义数据结构文件夹中的某个东西,一年只使用一到两次。好的。好啊。
首先,在python 2中引入了有序字典和命名元组,但这并不是重点。
我不会指给你看这些文件,因为如果你真的感兴趣的话,你已经读过了。
集合类型之间的第一个区别是可变性。
如果你想要一些东西,你可以随机或按顺序访问,但最终主要会改变,你需要一个
你不能把你的蛋糕也吃了——你添加的每一个功能都会让你失去一些速度。
当您访问
总有一天,你会编码,然后你会说,"伙计,现在我确切地知道他们所说的‘应该有一个——最好只有一个——显而易见的方法来做它’,
所有这些专门的收集类型都提供特定的功能,而列表、元组、dict和set的"标准"数据类型没有充分或有效地提供这些功能。
例如,有时您需要一组唯一的项,并且您还需要保留遇到它们的顺序。您可以使用一个集合来跟踪成员身份,使用一个列表来跟踪顺序,但是您的解决方案可能会比专门为此目的设计的数据结构(如有序集合)更慢,也更需要内存。
这些附加的数据类型(您在基本数据类型上将其视为组合或变化)实际上填补了基本数据类型所留下的功能空白。从实践的角度来看,如果Python的核心或标准库没有提供这些数据类型,那么任何需要它们的人都会发明自己的低效版本。它们的使用频率低于基本类型,但通常足以使其在提供标准实现的同时具有价值。
字典是按键索引的(事实上,它是一个散列映射);元组的一般列表不会是。您可能会认为两者都应该作为关系来实现,可以随意添加索引,但是在实践中,为常见用例优化类型既方便又高效。
添加新的专门化集合是因为它们非常常见,以至于很多人最终都会使用更基本的数据类型来实现它们,然后您会遇到车轮重新设计的常见问题(浪费精力、缺乏互操作性…)。如果Python只是提供了一个完全通用的构造,那么我们会有很多人问"我如何使用关系实现集合"等等。
(顺便说一句,我使用的是数学或db意义上的关系)
The Zen of Python says"There should be one-- and preferably only one --obvious way to do it". It seems to me this profusion of specialized collections types is in conflict with this Python precept.
号
不是远程的。这里有几个不同的事情要做。我们为这项工作选择了合适的工具。所有这些容器都是根据几十年前经过试验、测试和真实的CS概念建模的。
字典不像元组:它们是为键值查找而优化的。元组也是不可变的,它区别于一个列表(您可以把它看作是一个
命名元组的存在是为了方便,实际上是为了替换简单的类而不是字典。有序字典只是有点包装,以记住添加到字典中的内容的顺序。在3.x中,这两种语言都不是新的(尽管可能有更好的语言支持,但我还没有找到)。
数据结构(语言不可知论)的世界通常可以归结为一些小的基本结构——列表、树、哈希表和图等,以及它们的变体和组合。在使用和实现方面,每种方法都有其特定的用途。
我不认为你可以在不指定字典的情况下,将字典简化为具有特定唯一性约束的元组列表。字典有一个特定的用途——键/值查找——数据结构的实现通常是根据这些需求而定制的。集合在许多方面与字典相似,但对集合的某些操作在字典上没有意义(联合、分离等)。
我不认为这违背了"Python禅"的做事方式。虽然您可以使用已排序的字典来执行字典所做的操作,而不使用已排序的部分,但您更违反了Occam的Razor,可能会导致性能损失。我认为这与能够以不同的方式在语法上处理La Perl有所不同。
在Python中,我最喜欢的是敏捷性。很多功能性的、有效的和可用的集合类型都给了我。
还有一种方法可以做到这一点——每种类型都有自己的工作。