发布于2019-09-21 10:52 阅读(257) 评论(0) 点赞(26) 收藏(1)
python是否具有像cons
OCaml(::
)(或lisp)中那样的列表构造函数,它接受head
元素和tail
列表,并返回新列表head::tail
?
我搜索了python列表构造函数,最后发现了有关的其他信息__init__
。参见例如在Python中创建列表-偷偷摸摸地发生了什么?
为了澄清,我正在寻找的是在此问题中发现的以下Python列表分解的逆过程:
head, *tail = [1, 1, 2, 3, 5, 8, 13, 21, 34, 55]
这给出:
>>>head
1
>>> tail
[1, 2, 3, 5, 8, 13, 21, 34, 55]
我正在寻找一个列表构造器,例如cons
或::
这样
head :: tail => original list
要回答您的问题,没有与您通常在所谓的“功能”语言(lisp,OCaml,Haskell等)中发现的缺点直接等效的东西。
这是因为有两个相互竞争的模型来表示编程语言中的元素列表。
您似乎熟悉的一个称为链表。
链表由cons单元组成,每个单元包含两个引用:
因为列表很少是无限的,所以最后一个const单元通常会指向一个特殊值,即空列表,有时称为nil。
如果要将列表保存在变量中以备将来参考,则应保留对第一个cons单元的引用。
在此模型中,必须通过创建一个新的cons单元格在前面添加元素来构造每个列表,指向该新元素作为其头部,并指向先前构造的子列表作为其尾部。这就是为什么cons运算符有时称为list构造函数的原因。
这是命令式语言(例如Python)通常首选的模型。在此模型中,列表只是对内存范围的引用。
假设您像这样创建一个列表:
l = [1, 2, 3]
每当您创建列表时,Python都会为其分配一小段内存来存储元素,并留有一些额外的空间,以防万一您以后想要添加元素。要存储它,您只需存储对第一个元素的引用以及对内存范围大小的引用,就像这样:
l <-- your variable
| ___ ___ ___ ___ ___ ___ ___ ___ ___
|-> | | | | | | | | | |
| 1 | 2 | 3 | | | | | | |
|___|___|___|___|___|___|___|___|___|
如果您决定在列表末尾添加元素,则可以使用 append
l.append(4)
产生以下列表:
___ ___ ___ ___ ___ ___ ___ ___ ___
| | | | | | | | | |
| 1 | 2 | 3 | 4 | | | | | |
|___|___|___|___|___|___|___|___|___|
现在,假设您忘记了一个初始0,现在希望将其添加到前面。您真的可以很好地使用insert方法(插入位置为0):
l.insert(0, 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个点!
如果您需要多次访问非常大的列表中的随机元素,那么数组会更好。
假设您现在想在中间插入一个元素。
带有链表:
使用数组时,就像在中间添加元素一样,您将需要将每个元素复制到插入点的右边,在右边留一个空格!
在这种情况下,这就是明显更好的链表。
作者:黑洞官方问答小能手
链接:https://www.pythonheidong.com/blog/article/118019/af84061a156cf235db0c/
来源:python黑洞网
任何形式的转载都请注明出处,如有侵权 一经发现 必将追究其法律责任
昵称:
评论内容:(最多支持255个字符)
---无人问津也好,技不如人也罢,你都要试着安静下来,去做自己该做的事,而不是让内心的烦躁、焦虑,坏掉你本来就不多的热情和定力
Copyright © 2018-2021 python黑洞网 All Rights Reserved 版权所有,并保留所有权利。 京ICP备18063182号-1
投诉与举报,广告合作请联系vgs_info@163.com或QQ3083709327
免责声明:网站文章均由用户上传,仅供读者学习交流使用,禁止用做商业用途。若文章涉及色情,反动,侵权等违法信息,请向我们举报,一经核实我们会立即删除!