Ink*_*ane 18 python python-2.x
在Python(2.7.2)中,为什么呢
import dis
dis.dis("i in (2, 3)")
Run Code Online (Sandbox Code Playgroud)
按预期工作,而
import dis
dis.dis("i in [2, 3]")
Run Code Online (Sandbox Code Playgroud)
提出:
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
Run Code Online (Sandbox Code Playgroud)
请注意,这不会影响Python3.
Kat*_*iel 29
在Python 2.x中,str
类型包含原始字节,因此dis
假设如果您传递一个字符串,它将获得编译的字节码.它试图反汇编你传递它作为字节码的字符串 - 纯粹由于Python字节码的实现细节 - 成功i in (2,3)
.但显然,它会带来胡言乱语.
在Python 3.x中,str
类型用于字符串,bytes
类型用于原始字节,因此dis
可以区分已编译的字节码和字符串 - 并假设它获取源代码(如果它获取字符串).
这是我遵循的思考过程.
我在我的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
Run Code Online (Sandbox Code Playgroud)
显然,这是有效的.
我在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
Run Code Online (Sandbox Code Playgroud)
啊哈!另请注意,Python 3.2中生成的字节码是您所期望的("加载i
,加载(2,3)
,测试成员资格,返回结果"),而您在Python 2.7中获得的是乱码.显然,dis
在2.7中将字符串反编译为字节码,但在3.2中将其编译为Python.
我查看了源代码dis.dis
.以下是要点:
Python 2.7:
elif isinstance(x, str):
disassemble_string(x)
Run Code Online (Sandbox Code Playgroud)
Python 3.2:
elif isinstance(x, (bytes, bytearray)): # Raw bytecode
_disassemble_bytes(x)
elif isinstance(x, str): # Source code
_disassemble_str(x)
Run Code Online (Sandbox Code Playgroud)
只是为了好玩,让我们通过dis
在Python 3中传递相同的字节来检查:
>>> 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>
Run Code Online (Sandbox Code Playgroud)
啊哈!胡言乱语!(虽然请注意它的乱码略有不同 - 字节码随Python版本而改变!)
geo*_*org 18
dis.dis
期望字节码作为参数,而不是python源代码.虽然您的第一个示例"有效",但它不提供任何有意义的输出.你可能想要:
import compiler, dis
code = compiler.compile("i in [2, 3]", '', 'single')
dis.dis(code)
Run Code Online (Sandbox Code Playgroud)
这按预期工作.(我只在2.7中测试过).
如果你只是想为一个简单的表达式获取字节码,将它作为lambda传递给dis,你的表达式作为lambda的主体是最简单的:
>>> import dis
>>> dis.dis(lambda i : i in [3,2])
1 0 LOAD_FAST 0 (i)
3 LOAD_CONST 2 ((3, 2))
6 COMPARE_OP 6 (in)
9 RETURN_VALUE
Run Code Online (Sandbox Code Playgroud)
归档时间: |
|
查看次数: |
1115 次 |
最近记录: |