本文出自“Python为什么”系列,请查看全部文章

在日常使用 Python 时,我们经常需要创建一个列表,相信大家都很熟练了吧?

# 方法一:使用成对的方括号语法
list_a = [] # 方法二:使用内置的 list()
list_b = list()

上面的两种写法,你经常使用哪一个呢?是否思考过它们的区别呢?

让我们开门见山,直接抛出本文的问题吧:两种创建列表的 [] 与 list() 写法,哪一个更快呢,为什么它会更快呢?

注:为了简化问题,我们以创建空列表为例进行分析。关于列表的更多介绍与用法说明,可以查看这篇文章

1、 [] 是 list() 的三倍快

对于第一个问题,使用timeit模块的 timeit() 函数就能简单地测算出来:

>>> import timeit
>>> timeit.timeit('[]', number=10**7)
>>> timeit.timeit('list()', number=10**7)

如上图所示,在各自调用一千万次的情况下,[] 创建方式只花费了 0.47 秒,而 list() 创建方式要花费 1.75 秒,所以,后者的耗时是前者的 3.7 倍!

这就回答了刚才的问题:创建空列表时,[] 要比 list() 快不少。

注:timeit() 函数的效率跟运行环境相关,每次执行结果会有微小差异。我在 Python3.8 版本实验了几次,总体上 [] 速度是 list() 的 3 倍多一点。

2、list() 比 [] 执行步骤多

那么,我们继续来分析一下第二个问题:为什么 [] 会更快呢?

这一次我们可以使用dis模块的 dis() 函数,看看两者执行的字节码有何差别:

>>> from dis import dis
>>> dis("[]")
>>> dis("list()")

如上图所示,[] 的字节码有两条指令(BUILD_LIST 与 RETURN_VALUE),而 list() 的字节码有三条指令(LOAD_NAME、CALL_FUNCTION 与 RETURN_VALUE)。

这些指令意味着什么呢?该如何理解它们呢?

首先,对于 [],它是 Python 中的一组字面量(literal),像数字之类的字面量一样,表示确切的固定值。

也就是说,Python 在解析到它时,就知道它要表示一个列表,因此会直接调用解释器中构建列表的方法(对应 BUILD_LIST ),来创建列表,所以是一步到位。

而对于 list(),“list”只是一个普通的名称,并不是字面量,也就是说解释器一开始并不认识它。

因此,解释器的第一步是要找到这个名称(对应 LOAD_NAME)。它会按照一定的顺序,在各个作用域中逐一查找(局部作用域--全局作用域--内置作用域),直到找到为止,找不到则会抛出NameError

解释器看到“list”之后是一对圆括号,因此第二步是把这个名称当作可调用对象来调用,即把它当成一个函数进行调用(对应 CALL_FUNCTION)。

因此,list() 在创建列表时,需要经过名称查找与函数调用两个步骤,才能真正开始创建列表(注:CALL_FUNCTION 在底层还会有一些函数调用过程,才能走到跟 BUILD_LIST 相通的逻辑,此处我们忽略不计)。

至此,我们就可以回答前面的问题了:因为 list() 涉及的执行步骤更多,因此它比 [] 要慢一些。

3、list() 的速度提升

看完前两个问题的解答过程,你也许觉得还不够过瘾,而且可能觉得就算知道了这个冷知识,也不会有多大的帮助,似乎那微弱的提升显得微不足道。

但是,我们Python猫出品的《Python为什么》系列一直秉承着孜孜不倦的求知精神,是不可能放着这个问题不去回答的。

而且,由于有发散性思考的习惯,我还想到了另外一个挺有意思的问题:list() 的速度能否提升呢?

我不久前写过一篇文章 正好讨论到这个问题,也就是在刚刚发布的 Python 3.9.0 版本中,它给 list() 实现了更快的 vectorcall 协议,因此执行速度会有一定的提升。

感兴趣的同学可以去Python 官网下载 3.9 版本。

根据我多轮的测试结果,在新版本中运行 list() 一千万次,耗时大概在 1 秒左右,也就是 [] 运行耗时的 2 倍,相比于前面接近 4 倍的数据,当前版本总体上是提升了不少。

至此,我们已回答完一连串的疑问,如果你觉得有收获,请点赞支持!欢迎大家关注后续更多精彩内容。

本文属于“Python为什么”系列(Python猫出品),该系列主要关注 Python 的语法、设计和发展等话题,以一个个“为什么”式的问题为切入点,试着展现 Python 的迷人魅力。所有文章将会归档在 Github 上,欢迎大家给颗小星星,项目地址:https://github.com/chinesehuazhou/python-whydo

Python 疑难问题:[] 与 list() 哪个快?为什么快?快多少呢?的更多相关文章

  1. 在python中创建列表的最佳和/或最快方法

    在python中,据我所知,至少有3到4种方法来创建和初始化给定大小的列表: 简单循环append: my_list = [] for i in range(50): my_list.append(0 ...

  2. 【转】TCP拥塞控制,慢启动、拥塞避免、快重传以及快恢复

    转自:http://blog.csdn.net/yusiguyuan/article/details/22847787 注:本文绝大部分是来自转载的博客,还补充了少量内容. 一.TCP的拥塞控制 拥塞 ...

  3. TCP超时重传、滑动窗口、拥塞控制、快重传和快恢复

    TCP超时重传 原理是在发送某一个数据以后就开启一个计时器,在一定时间内如果没有得到发送的数据报的ACK报文,那么就重新发送数据,直到发送成功为止. 影响超时重传机制协议效率的一个关键参数是重传超时时 ...

  4. TCP/IP学习笔记18--TCP--拥塞控制 (慢开始, 拥塞避免, 快重传和快恢复)

                                                            用最多的梦面对未来   -- 李嘉诚 在某段时间,若对网络资源的需求超过了该资源所能提供 ...

  5. 通信接口是webservice快还是scoket快解决方案

    通信接口是webservice快还是scoket快webservice和scoket都可以做为通信接口,一个走HTTP访问,一个走TCP协议访问 问1:通讯速度是webservice快还是scoket ...

  6. 计算机网络传输层之TCP拥塞控制(慢开始与拥塞避免、快重传和快恢复)

    文章转自:https://blog.csdn.net/weixin_43914604/article/details/105532044 学习课程:<2019王道考研计算机网络> 学习目的 ...

  7. 用python批量处理Excel表格,处理结果又快又好,做办公室最靓的那个仔

    使用python批量处理Excel数据     让你根据Excel上所有人的身份证号码,提取出公司员工的生日 让你每个月都将公司所有人的考勤数据整理一下 类似这样的格式化的重复操作,你还在每次都使用的 ...

  8. postman python疑难

    例子1:postman请求时会将默认的headers的content-type替换成Content-Type,而直接使用python的request则不行,服务器端就会接收到错误的Content-Ty ...

  9. 先贴上代码:Random快排,快排的非递归实现

    设要排序的数组是A[0]……A[N-1],首先任意选取一个数据(通常选用数组的第一个数)作为主元,然后将所有比它小的数都放到它前面,所有比它大的数都放到它后面,这个过程称为一趟快速排序.值得注意的是, ...

随机推荐

  1. 15_Web框架-mini frame

    1.WSGI协议概述(Python Web Server Gateway Interface) 1.WSGI允许开发者将选择web框架和web服务器分开,可以混合匹配web服务器和web框架,选择一个 ...

  2. 《闲扯Redis十一》Redis 有序集合对象底层实现

    一.前言 Redis 提供了5种数据类型:String(字符串).Hash(哈希).List(列表).Set(集合).Zset(有序集合),理解每种数据类型的特点对于redis的开发和运维非常重要. ...

  3. 手把手教你 在Pytorch框架上部署和测试 关键点人脸检测项目DBFace,成功实现人脸检测效果

    这期教向大家介绍仅仅 1.3M 的轻量级高精度的关键点人脸检测模型DBFace,并手把手教你如何在自己的电脑端进行部署和测试运行,运行时bug解决. 01. 前言 前段时间DBFace人脸检测库横空出 ...

  4. 【二叉树-BFS系列1】二叉树的右视图、二叉树的锯齿形层次遍历

    题目 199. 二叉树的右视图 给定一棵二叉树,想象自己站在它的右侧,按照从顶部到底部的顺序,返回从右侧所能看到的节点值. 示例: 输入: [1,2,3,null,5,null,4] 输出: [1, ...

  5. 再学ajax--第二天 | 基于php+mysql+ajax的表单注册、登录、注销

    写在前面 ajax学习到了第二天,这次是用第一天封装的ajax函数,后端使用了php+mysql实现基本的注册,登录,注销. php是我前几个月get到的技能,我已经学习到了面向对象,知道各修饰符的含 ...

  6. MaaS系统概述

    摘要:共享经济正改变着人们的生活方式,城市公共交通系统应该顺应共享经济的潮流进行转型.近年来,西方国家提出的“出行即服务(MaaS)”理念为我国解决日益严重的城市交通拥堵问题提供了新的思路.基于Maa ...

  7. springcloud一些博文记录

    自己搭建完整demo后看的一个系列博文https://my.oschina.net/u/3375733/following 现在看着这个系列的后期文章估计出差前不会看了 一个博主的系列的git地址和博 ...

  8. maven安装配置以及eclipse的配置

    一.需要准备的东西 JDK Eclipse Maven程序包 二.下载与安装 前往https://maven.apache.org/download.cgi下载最新版的Maven程序: 将文件解压到D ...

  9. Cypress系列(60)- 运行时的截图和录屏

    如果想从头学起Cypress,可以看下面的系列文章哦 https://www.cnblogs.com/poloyy/category/1768839.html 背景 在测试运行时截图和录屏能够在测试错 ...

  10. 小白也能看懂的Redis教学基础篇——朋友面试被Skiplist跳跃表拦住了

    各位看官大大们,双节快乐 !!! 这是本系列博客的第二篇,主要讲的是Redis基础数据结构中ZSet(有序集合)底层实现之一的Skiplist跳跃表. 不知道那些是Redis基础数据结构的看官们,可以 ...