Python中列表切片[:]与[::]的区别解析

Ivy
Ivy
发布时间:2026-10-13| 6人浏览过
原创

本文深入探讨Python中列表切片[:]和[::]在复制列表时的异同。在Python 3中,两者生成的字节码完全一致,无性能差异;但在Python 2.x中,[:]因指令更少而略高效。文章通过dis模块分析字节码,并指出该特性适用于所有序列类型,建议开发者根据版本选择写法。

前言

new = old[:]

经验丰富的Python开发者通常清楚上述代码的含义:它将列表old浅拷贝至new。尽管这种方法对初学者而言可能令人困惑且不建议使用,但[:]切片法依然被广泛采用,部分原因可能是许多Python程序员尚未了解更优的列表复制方式。本文将详细解析Python在复制列表时[:]与[::]之间的具体区别,供读者参考。

我们可以使用[:]对列表进行浅拷贝:

l = [1, 2, 3]
z1 = l[:]

同样,我们也可以使用[::]对其进行浅拷贝:

z2 = [::]

此时,表达式z1 == z2的结果为True。在查阅《Explain Python's slice notation》一文后,我理解了这些切片操作的工作原理。

然而,我的核心疑问在于:这两种写法内部是否存在差异?在复制操作中,哪一种效率更高,或者它们是否执行完全相同的逻辑?

最佳答案

在Python 3中,两者之间绝对没有区别。如果感兴趣,可以使用dis.dis函数检查它们生成的字节码:

l = [1, 2, 3, 4]

针对表达式l[:]发出的字节码如下:

from dis import dis
dis('l[:]')
 1   0 LOAD_NAME    0 (l)
    3 LOAD_CONST    0 (None)
    6 LOAD_CONST    0 (None)
    9 BUILD_SLICE    2
    12 BINARY_SUBSCR
    13 RETURN_VALUE

而针对表达式l[::]发出的字节码如下:

dis('l[::]')
 1   0 LOAD_NAME    0 (l)
    3 LOAD_CONST    0 (None)
    6 LOAD_CONST    0 (None)
    9 BUILD_SLICE    2
    12 BINARY_SUBSCR
    13 RETURN_VALUE

从输出可见,两者完全一致。对于构建切片(BUILD_SLICE)操作,起始值和停止值均加载了None(通过两个LOAD_CONST指令)。None是标准类型层次结构中切片文档所定义的默认值:

Special read-only attributes: start is the lower bound; stop is the upper bound; step is the step value; each is None if omitted. These attributes can have any type.

从代码书写的角度来看,使用[:]所需的击键次数更少。

有趣的是,在Python 2.x版本中,生成的字节码存在差异。由于l[:]涉及的指令较少,它可能会稍微高效一些:

>>> def foo():
...  l[:]
... 
>>> dis(foo)
 2   0 LOAD_GLOBAL    0 (l)
    3 SLICE+0    
    4 POP_TOP    
    5 LOAD_CONST    0 (None)
    8 RETURN_VALUE 

而对于l[::]的情况:

>>> def foo2():
...  l[::]
... 
>>> dis(foo2)
 2   0 LOAD_GLOBAL    0 (l)
    3 LOAD_CONST    0 (None)
    6 LOAD_CONST    0 (None)
    9 LOAD_CONST    0 (None)
    12 BUILD_SLICE    3
    15 BINARY_SUBSCR  
    16 POP_TOP    
    17 LOAD_CONST    0 (None)
    20 RETURN_VALUE 

尽管我未对这两种情况进行严格计时(差异预期极小),但仅从指令数量来看,l[:]似乎略占优势。

这种相似性不仅限于列表,它同样适用于Python中的所有序列类型:

# Note: the Bytecode class exists in Py > 3.4
>>> from dis import Bytecode
>>>
>>> Bytecode('(1, 2, 3)[:]').dis() == Bytecode('(1, 2, 3)[::]').dis() 
True
>>> Bytecode('"string"[:]').dis() == Bytecode('"string"[::]').dis() 
True

其他序列类型也是如此。

总结

以上就是本文的全部内容,希望本文的解析对大家的学习或工作具有一定的参考价值。如有疑问,欢迎留言交流,感谢大家对本站的支持。

相关标签:

免责声明:本文内容仅供参考,不代表本站观点。转载或引用请注明出处。

Python 相关产品和应用

全部下载
Selenium

Selenium

4.51.0 · Windows

用于浏览器自动化和 Web 测试的 Python 工具。

scikit-learn

scikit-learn

1.9.1 · Windows

常用 Python 机器学习算法与模型评估工具库。

Black

Black

26.10.1 · Windows

强调一致性的 Python 自动代码格式化工具。

Ruff

Ruff

0.17.1 · macOS

由 Rust 编写的高速 Python 代码检查和格式化工具。

pytest

pytest

9.1.1 · Windows

简洁而强大的 Python 自动化测试框架。

FastAPI

FastAPI

0.146.0 · Windows

高性能 Python API 框架,支持类型提示和自动接口文档。

Flask

Flask

3.1.3 · Windows

轻量灵活的 Python Web 应用框架。

Django

Django

6.1.2 · Windows

成熟的 Python Web 框架,适合构建内容站点和业务系统。

Spyder

Spyder

6.1.7 · Windows

面向科学计算与数据分析的 Python 集成开发环境。

SciPy

SciPy

1.18.1 · Windows

面向科学、工程和技术计算的 Python 算法库。