我现在正在学习Python,我们只是将元组作为数据类型之一.我阅读了维基百科页面,但是,我无法弄清楚这种数据类型在实践中的用处.我是否可以在Python中提供一些示例,其中需要一组不可变的数字?这与列表有什么不同?
只要您想从函数返回多个结果,就会使用元组.
由于它们是不可变的,因此它们可以用作字典的键(列表不能).
当你需要将多个数据组合到你的密钥中时,元组会生成很好的字典密钥,而不想为它创建一个类.
a = {} a[(1,2,"bob")] = "hello!" a[("Hello","en-US")] = "Hi There!"
我主要使用此功能来创建一个字典,其中的键是网格顶点的坐标.但是,在我的特定情况下,所涉及的浮点数的精确比较工作正常,这可能并不总是适用于您的目的[在这种情况下我可能会将您的传入浮点数转换为某种定点整数]
我喜欢这个解释.
基本上,当有一个常量结构时,你应该使用元组(第一个位置总是包含一种类型的值,而第二个位置总是包含另一个,依此类推),并且列表应该用于同类值列表.
当然总有例外,但这是一个很好的一般准则.
最好的考虑方法是:
元组是其字段没有名称的记录。
当您不必麻烦指定字段名称时,可以使用元组而不是记录。
因此,与其像这样写东西:
person = {"name": "Sam", "age": 42} name, age = person["name"], person["age"]
或者更冗长:
class Person: def __init__(self, name, age): self.name = name self.age = age person = Person("Sam", 42) name, age = person.name, person.age
您可以这样写:
person = ("Sam", 42) name, age = person
当您要传递仅具有几个字段的记录或仅在少数地方使用的记录时,此功能很有用。在这种情况下,使用字段名称指定全新的记录类型(在Python中,您将使用对象或字典,如上所述)可能太冗长。
元组源自函数式编程领域(Haskell,OCaml,Elm,F#等),在该领域中它们通常用于此目的。与Python不同,大多数函数式编程语言都是静态类型的(变量只能保存一种类型的值,而该类型是在编译时确定的)。静态类型使元组的作用更加明显。例如,使用榆木语言:
type alias Person = (String, Int) person : Person person = ("Sam", 42)
这凸显了这样一个事实,即特定类型的元组总是应该以固定的顺序具有固定数量的字段,并且这些字段中的每个字段总是应该具有相同的类型。在此示例中,一个人始终是两个字段的元组,一个是字符串,另一个是整数。
上面与list形成了鲜明的对比,list应该是可变长度的(每个列表中的项目数通常是不同的,并且您编写了添加和删除项目的函数),并且列表中的每个项目通常是同一类型。例如,您将拥有一个人员列表和另一个地址列表-您不会在同一列表中混合人员和地址。而在同一元组中混合不同类型的数据是元组的重点。元组中的字段通常具有不同的类型(但并非总是如此-例如,您可以有一个(Float, Float, Float)
元组来表示x,y,z坐标)。
元组和列表通常是嵌套的。有一个元组列表是很常见的。您可以拥有一个Person元组列表以及一个Person对象列表。您还可以具有一个元组字段,其值是一个列表。例如,如果您有一个地址簿,其中一个人可以有多个地址,则您可以有一个type的元组(Person, [String])
。该[String]
类型通常在函数式编程语言中用来表示字符串列表。在Python中,您不会写下类型,但是可以以完全相同的方式使用类似的元组,将Person
对象放在元组的第一个字段中,并在其第二个字段中放入字符串列表。
在Python中,由于该语言不执行由编译器在静态类型的函数式语言中强制执行的任何这些实践,因此会引起混淆。在这些语言中,不能混合使用不同类型的元组。例如,您不能(String, String)
从其类型表示返回元组的函数返回(String, Integer)
元组。当类型表明您计划返回元组时,您也不能返回列表,反之亦然。列表严格用于增长项目集合,而元组严格用于固定大小的记录。如果您愿意,Python不会阻止您违反任何这些规则。
在Python中,列表有时会转换为元组以用作字典键,因为Python字典键需要是不可变的(即常量)值,而Python列表是可变的(您可以随时添加和删除项)。这是针对Python中特定限制的解决方法,而不是作为计算机科学概念的元组的属性。
因此,在Python中,列表是可变的,元组是不可变的。但这只是设计选择,而不是计算机科学中列表和元组的固有属性。您也可以拥有不可变的列表和可变的元组。
在Python中(使用默认的CPython实现),在大多数情况下,元组也比对象或字典快,因此出于某种原因偶尔使用它们,即使使用对象或字典命名字段时也会更清楚。
最后,为了使元组打算成为另一种记录(而不是另一种列表)更加明显,Python还命名了元组:
from collections import namedtuple Person = namedtuple("Person", "name age") person = Person("Sam", 42) name, age = person.name, person.age
通常,这是最佳选择-比定义新类短,但是与使用不带名称的普通元组相比,这些字段的含义更加明显。
不可变列表对于许多目的非常有用,但是这个主题太复杂了,无法在此处回答。要点是,无法改变的事物比可以改变的事物更容易推理。大多数软件错误来自事物以意想不到的方式发生变化,因此限制它们可以更改的方式是消除错误的好方法。如果您有兴趣,建议阅读有关Elm,Haskell或Clojure等功能性编程语言的教程(Elm是最友好的语言)。这些语言的设计师认为不变性非常有用,以至于所有列表在那里都是不变的。(而不是更改列表以添加和/或删除项目,而是创建一个添加或删除项目的新列表。不变性保证了列表的旧副本永远不会改变,因此编译器和运行时可以通过在新列表中重用旧列表的一部分并在较长的剩余列表中进行垃圾回收来使代码性能良好需要。)