gpt4 book ai didi

python - 为什么 Python 的不喜欢列表?

转载 作者:IT老高 更新时间:2023-10-28 20:57:04 26 4
gpt4 key购买 nike

在Python(2.7.2)中,为什么

import dis
dis.dis("i in (2, 3)")

按预期工作,而

import dis
dis.dis("i in [2, 3]")

加注:

Traceback (most recent call last):
File "<stdin>", line 1, in <module>
File "/usr/lib/python2.7/dis.py", line 45, in dis
disassemble_string(x)
File "/usr/lib/python2.7/dis.py", line 112, in disassemble_string
labels = findlabels(code)
File "/usr/lib/python2.7/dis.py", line 166, in findlabels
oparg = ord(code[i]) + ord(code[i+1])*256
IndexError: string index out of range

请注意,这不会影响 Python3。

最佳答案

简答

在 Python 2.x 中,str 类型保存原始字节,因此 dis 假定如果您将字符串传递给它,它就会得到编译后的字节码。它尝试将您作为字节码传递的字符串反汇编,并且——纯粹是由于 Python 字节码的实现细节——对于 i in (2,3) 成功。但显然,它返回的是乱码。

在 Python 3.x 中,str 类型用于 stringsbytes 类型用于原始字节,因此 dis 可以区分编译后的字节码和字符串——如果它得到一个字符串就假设它正在获取源代码。


长答案

这是我为解决这个问题所遵循的思考过程。

  1. 我在我的 Python (3.2) 上尝试过:

    >>> import dis
    >>> dis.dis("i in (2,3)")
    1 0 LOAD_NAME 0 (i)
    3 LOAD_CONST 2 ((2, 3))
    6 COMPARE_OP 6 (in)
    9 RETURN_VALUE
    >>> dis.dis("i in [2,3]")
    1 0 LOAD_NAME 0 (i)
    3 LOAD_CONST 2 ((2, 3))
    6 COMPARE_OP 6 (in)
    9 RETURN_VALUE

    显然,这是可行的。

  2. 我在 Python 2.7 上试过:

    >>> import dis
    >>> dis.dis("i in (2,3)")
    0 BUILD_MAP 26912
    3 JUMP_FORWARD 10272 (to 10278)
    6 DELETE_SLICE+0
    7 <44>
    8 DELETE_SLICE+1
    9 STORE_SLICE+1
    >>> dis.dis("i in [2,3]")
    Traceback (most recent call last):
    File "<stdin>", line 1, in <module>
    File "C:\Python27\lib\dis.py", line 45, in dis
    disassemble_string(x)
    File "C:\Python27\lib\dis.py", line 112, in disassemble_string
    labels = findlabels(code)
    File "C:\Python27\lib\dis.py", line 166, in findlabels
    oparg = ord(code[i]) + ord(code[i+1])*256
    IndexError: string index out of range

    啊哈!另请注意,Python 3.2 中生成的字节码是您所期望的(“加载 i,加载 (2,3),测试成员资格,返回结果”)而你在 Python 2.7 中得到的东西是乱码。显然,dis 在 2.7 中将字符串反编译为字节码,但在 3.2 中将其编译为 Python。

  3. 我查看了 dis.dis 的源代码。以下是重点:

    Python 2.7:

    elif isinstance(x, str):
    disassemble_string(x)

    Python 3.2:

       elif isinstance(x, (bytes, bytearray)): # Raw bytecode
    _disassemble_bytes(x)
    elif isinstance(x, str): # Source code
    _disassemble_str(x)

    为了好玩,让我们通过在 Python 3 中将相同的字节传递给 dis 来检查一下:

    >>> dis.dis("i in (2,3)".encode())
    0 BUILD_MAP 26912
    3 JUMP_FORWARD 10272 (to 10278)
    6 <50>
    7 <44>
    8 <51>
    9 <41>

    啊哈!胡言乱语! (但请注意,它的胡言乱语略有不同——字节码已随 Python 版本而变化!)

关于python - 为什么 Python 的不喜欢列表?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/10473744/

26 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com