python有列表构造函数吗?

python有列表构造函数吗?,python,list,Python,List,python是否有像OCaml(:)(或lisp)中的cons(或lisp)这样的列表构造函数,它接受head元素和tail列表,并返回一个新的列表head::tail 我搜索了python列表构造函数,最后找到了关于\uuuu init\uuuu的其他内容。见例 为了澄清,我要寻找的是Python中以下列表分解的相反形式: 这使得: >>>head 1 >>> tail [1, 2, 3, 5, 8, 13, 21, 34, 55] 我正在寻找一个列表构造

python是否有像OCaml(
)(或lisp)中的
cons
(或lisp)这样的列表构造函数,它接受
head
元素和
tail
列表,并返回一个新的列表
head::tail

我搜索了python列表构造函数,最后找到了关于
\uuuu init\uuuu
的其他内容。见例

为了澄清,我要寻找的是Python中以下列表分解的相反形式:

这使得:

>>>head
1
>>> tail
[1, 2, 3, 5, 8, 13, 21, 34, 55]
我正在寻找一个列表构造函数,例如
cons
这样

head :: tail  =>   original list

Python列表是可变的,而OCaml列表具有不可变的值语义,但是如果
a
是一个项,
b
是一个列表,则可以使用
[a]+b
返回一个新列表,其中包含
a
,后跟
b
中的项,并且不修改
a
b
。不过,构建列表的一种更常见的模式是
附加
扩展
它。

您可以使用列表连接

head = 1
tail = [2,3,4]
lst = [head] + tail # [1,2,3,4]

有些人建议你这样做:

a = 1
b = [2, 3, 4, 5]
c = [a] + b
如果
b
类型为
list
,则该选项将起作用。但是,您经常会发现自己使用的对象是列表或元组或(在此处插入您最喜欢的iterable对象)。在这种情况下,您可能更值得这样做:

a = 1
b = (2, 3, 4, 5)
c = [a]
c.extend(b)
这使得整个事情对
b
的类型不可知(这允许您的代码更“ducky”,这可能有点好)


当然,还有其他选择。例如,您可以选择访问
itertools

import itertools
a = 1
b = [2, 3, 4, 5]
lazy_c = itertools.chain([a], b)

同样,我们不关心iterable
b
是什么类型的,这是一个好处,而且我们还得到了懒洋洋地迭代的一个附带好处——我们不会创建新的列表或元组。我们将创建一个对象,当您对它进行迭代时,它将产生相同的结果。这可以节省内存(有时还可以节省CPU的周期),但如果
b
也是一种类似生成器的对象,同时在其他地方进行迭代(这不是经常发生的),也可能会产生意想不到的后果。

回答您的问题,在所谓的“函数式”语言(lisp、OCaml、Haskell等)中,没有直接的等价物

这是因为在编程语言中有两个相互竞争的模型来表示元素列表

链表 你似乎熟悉的一个叫做链表

链表由cons单元格组成,每个单元格包含两个引用:

  • 第一个指向列表中的一个元素,称为head
  • 另一个指向列表中的下一个cons单元格,是尾部
由于列表很少是无限的,最后一个常量单元格通常指向一个特殊值,即空列表,有时称为nil

如果希望将列表保存在变量中以供将来引用,则应保留对第一个单元格的引用

在这个模型中,每个列表都必须通过创建一个新的cons单元,将元素添加到前面来构建,将新元素作为其头部,将先前构建的子列表作为其尾部。这就是cons运算符有时被称为列表构造函数的原因

阵列 这是命令式语言(如Python)通常首选的模型。在这个模型中,列表只是对内存中某个范围的引用

假设您创建一个如下所示的列表:

l = [1, 2, 3]
l  <-- your variable
|     ___ ___ ___ ___ ___ ___ ___ ___ ___
|->  |   |   |   |   |   |   |   |   |   |
     | 1 | 2 | 3 |   |   |   |   |   |   |
     |___|___|___|___|___|___|___|___|___|
每当您创建一个列表时,Python都会给它分配一个小范围的内存来存储元素,并留出一点额外的空间,以备以后添加元素时使用。要存储它,只需存储对第一个元素和内存范围大小的引用,如下所示:

l = [1, 2, 3]
l  <-- your variable
|     ___ ___ ___ ___ ___ ___ ___ ___ ___
|->  |   |   |   |   |   |   |   |   |   |
     | 1 | 2 | 3 |   |   |   |   |   |   |
     |___|___|___|___|___|___|___|___|___|
结果如下:

 ___ ___ ___ ___ ___ ___ ___ ___ ___
|   |   |   |   |   |   |   |   |   |
| 1 | 2 | 3 | 4 |   |   |   |   |   |
|___|___|___|___|___|___|___|___|___|
现在,假设您忘记了首字母0,现在希望将其添加到前面。您可以很好地使用insert方法(insert位置为0):

但是列表的开头没有空格!Python别无选择,只能将每个元素都复制到右边的位置:

 ___ ___ ___ ___ ___ ___ ___ ___ ___
|   |   |   |   |   |   |   |   |   |
| 1 | 2 | 3 | 4 |   |   |   |   |   |
|___|___|___|___|___|___|___|___|___|
  |   |   |__ |___
  |   |___   |    |  First, Python has to copy the four elements
  |___    |  |    |  one space to the right 
 ___ _\/ _\/ \/_ _\/ ___ ___ ___ ___
|   |   |   |   |   |   |   |   |   |
|   | 1 | 2 | 3 | 4 |   |   |   |   |
|___|___|___|___|___|___|___|___|___|

Only then can it insert the 0 at the beginning

 ___ ___ ___ ___ ___ ___ ___ ___ ___
|   |   |   |   |   |   |   |   |   |
| 0 | 1 | 2 | 3 |   |   |   |   |   |
|___|___|___|___|___|___|___|___|___|
对于这样一个小的数组来说,这似乎不算什么,但想象一下您的数组要大得多,并且您多次重复此操作:您将花费大量时间构建列表

这就是为什么在使用数组作为列表的语言(如Python)中找不到列表构造函数的原因

进一步潜水:为什么两种不同的模式? 您现在可能想知道为什么不同的语言会喜欢不同的列表模型,以及这两种模型中是否有一种更优越

这是因为这两种数据结构在不同的上下文中具有不同的性能。两个例子:

访问中间元素 假设您想要获取列表的第五个元素

在链接列表中,您需要获得:

  • 第一个囚室
  • 然后这个单元格的尾部得到第二个元素
  • 然后这个单元格的尾部得到第三个元素
  • 然后这个单元格的尾部得到第四个元素
  • 最后是这个单元格的尾部,得到第五个元素
因此,你必须通过5个参考

对于数组,这要简单得多:您知道第一个元素的引用。您只需要访问右边的参考4点,因为元素都在一个连续的内存范围内

如果需要多次访问非常大的列表中的随机元素,那么数组就更好了

在中间插入元素

假设你现在想在中间插入一个元素。

使用链接列表:

  • 找到与插入点前最后一个元素对应的cons单元格。 ___ ___ ___ ___ ___ ___ ___ ___ ___ | | | | | | | | | | | 1 | 2 | 3 | 4 | | | | | | |___|___|___|___|___|___|___|___|___| | | |__ |___ | |___ | | First, Python has to copy the four elements |___ | | | one space to the right ___ _\/ _\/ \/_ _\/ ___ ___ ___ ___ | | | | | | | | | | | | 1 | 2 | 3 | 4 | | | | | |___|___|___|___|___|___|___|___|___| Only then can it insert the 0 at the beginning ___ ___ ___ ___ ___ ___ ___ ___ ___ | | | | | | | | | | | 0 | 1 | 2 | 3 | | | | | | |___|___|___|___|___|___|___|___|___|