在 python 字节码中,fast 代表什么?
In python bytecode what does fast stand for?
如 LOAD_FAST
。 LOAD_CONST
很明显。或者也许 fast 只是代表 'fast' 并且是一种..加载局部变量的快速方法?
LOAD_FAST
用于局部变量,通过索引访问数组中的值。这比使用 LOAD_NAME
按名称访问字典中的变量值更快(从当前函数对象向外搜索所有范围)。
在 Python 2 中,可以通过使用数组 优化 函数局部变量,或者可以动态添加局部变量并需要使用 LOAD_NAME
.如果你使用 exec
statement 和 locals()
,那么局部变量不能被优化,因为 exec
可能添加任意局部变量,而 Python 不知道它们是局部的还是应该被视为全局变量:
>>> def optimised(bar): return bar
...
>>> dis.dis(optimised)
1 0 LOAD_FAST 0 (bar)
3 RETURN_VALUE
>>> def not_optimised(bar):
... exec bar
... return spam # global, or local? Python can't know
...
>>> not_optimised("spam = 42")
42
>>> not_optimised("ham = 'no spam!'")
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
File "<stdin>", line 3, in not_optimised
NameError: name 'spam' is not defined
>>> dis.dis(not_optimised)
2 0 LOAD_FAST 0 (bar)
3 LOAD_CONST 0 (None)
6 DUP_TOP
7 EXEC_STMT
3 8 LOAD_NAME 0 (spam)
11 RETURN_VALUE
这也反映在function.__code__.co_flags
标志变量中,设置了inspect.CO_OPTIMIZED
bit:
>>> import inspect
>>> bool(optimised.__code__.co_flags & inspect.CO_OPTIMIZED)
True
>>> bool(not_optimised.__code__.co_flags & inspect.CO_OPTIMIZED)
False
在 Python 3 中,删除了 exec
语句后,局部变量始终被优化,您不再可以动态设置局部变量。
LOAD_NAME
仍在 Python 3 中使用,但从未在关键代码中使用。当您使用 variable annotation 时,为创建 class 对象而生成的字节码使用 LOAD_NAME
来访问 __annotations__
映射,例如:
>>> import dis
>>> dis.dis("class Foo:\n bar: int\n")
1 0 LOAD_BUILD_CLASS
2 LOAD_CONST 0 (<code object Foo at 0x10e050df0, file "<dis>", line 1>)
4 LOAD_CONST 1 ('Foo')
6 MAKE_FUNCTION 0
8 LOAD_CONST 1 ('Foo')
10 CALL_FUNCTION 2
12 STORE_NAME 0 (Foo)
14 LOAD_CONST 2 (None)
16 RETURN_VALUE
Disassembly of <code object Foo at 0x10e050df0, file "<dis>", line 1>:
1 0 LOAD_NAME 0 (__name__)
2 STORE_NAME 1 (__module__)
4 LOAD_CONST 0 ('Foo')
6 STORE_NAME 2 (__qualname__)
8 SETUP_ANNOTATIONS
2 10 LOAD_NAME 3 (int)
12 LOAD_NAME 4 (__annotations__)
14 LOAD_CONST 1 ('bar')
16 STORE_SUBSCR
18 LOAD_CONST 2 (None)
20 RETURN_VALUE
如 LOAD_FAST
。 LOAD_CONST
很明显。或者也许 fast 只是代表 'fast' 并且是一种..加载局部变量的快速方法?
LOAD_FAST
用于局部变量,通过索引访问数组中的值。这比使用 LOAD_NAME
按名称访问字典中的变量值更快(从当前函数对象向外搜索所有范围)。
在 Python 2 中,可以通过使用数组 优化 函数局部变量,或者可以动态添加局部变量并需要使用 LOAD_NAME
.如果你使用 exec
statement 和 locals()
,那么局部变量不能被优化,因为 exec
可能添加任意局部变量,而 Python 不知道它们是局部的还是应该被视为全局变量:
>>> def optimised(bar): return bar
...
>>> dis.dis(optimised)
1 0 LOAD_FAST 0 (bar)
3 RETURN_VALUE
>>> def not_optimised(bar):
... exec bar
... return spam # global, or local? Python can't know
...
>>> not_optimised("spam = 42")
42
>>> not_optimised("ham = 'no spam!'")
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
File "<stdin>", line 3, in not_optimised
NameError: name 'spam' is not defined
>>> dis.dis(not_optimised)
2 0 LOAD_FAST 0 (bar)
3 LOAD_CONST 0 (None)
6 DUP_TOP
7 EXEC_STMT
3 8 LOAD_NAME 0 (spam)
11 RETURN_VALUE
这也反映在function.__code__.co_flags
标志变量中,设置了inspect.CO_OPTIMIZED
bit:
>>> import inspect
>>> bool(optimised.__code__.co_flags & inspect.CO_OPTIMIZED)
True
>>> bool(not_optimised.__code__.co_flags & inspect.CO_OPTIMIZED)
False
在 Python 3 中,删除了 exec
语句后,局部变量始终被优化,您不再可以动态设置局部变量。
LOAD_NAME
仍在 Python 3 中使用,但从未在关键代码中使用。当您使用 variable annotation 时,为创建 class 对象而生成的字节码使用 LOAD_NAME
来访问 __annotations__
映射,例如:
>>> import dis
>>> dis.dis("class Foo:\n bar: int\n")
1 0 LOAD_BUILD_CLASS
2 LOAD_CONST 0 (<code object Foo at 0x10e050df0, file "<dis>", line 1>)
4 LOAD_CONST 1 ('Foo')
6 MAKE_FUNCTION 0
8 LOAD_CONST 1 ('Foo')
10 CALL_FUNCTION 2
12 STORE_NAME 0 (Foo)
14 LOAD_CONST 2 (None)
16 RETURN_VALUE
Disassembly of <code object Foo at 0x10e050df0, file "<dis>", line 1>:
1 0 LOAD_NAME 0 (__name__)
2 STORE_NAME 1 (__module__)
4 LOAD_CONST 0 ('Foo')
6 STORE_NAME 2 (__qualname__)
8 SETUP_ANNOTATIONS
2 10 LOAD_NAME 3 (int)
12 LOAD_NAME 4 (__annotations__)
14 LOAD_CONST 1 ('bar')
16 STORE_SUBSCR
18 LOAD_CONST 2 (None)
20 RETURN_VALUE