[英]Does the global keyword inline the global exactly as a local variable declaration in python?
那么这两个在 vis 性能方面是否完全等效(即,生成的代码是否完全等效):
class A(object):
const = 'abc'
def lengthy_op(self):
const = self.const
for i in xrange(AVOGADRO):
# do something which involves reading const
和:
const = 'abc'
class A(object):
def lengthy_op(self):
global const
for i in xrange(AVOGADRO):
# do something which involves reading const
不,它们并不完全等效,尽管差异不太可能显着。
class A(object):
const = 'abc'
def lengthy_op(self):
const = self.const
for i in xrange(AVOGADRO):
# do something which involves reading const
这将创建一个局部变量,因此对 const 的任何访问都将使用LOAD_FAST
操作码。
const = 'abc'
class A(object):
def lengthy_op(self):
# global const
for i in xrange(AVOGADRO):
# do something which involves reading const
无论有没有冗余的global const
使用LOAD_GLOBAL
来访问全局变量const
、 xrange
和AVOGADRO
。
在 C Python LOAD_GLOBAL
将执行快速字典查找以访问变量(快速因为全局变量位于仅使用字符串键的字典中并且哈希值是预先计算的)。 另一方面, LOAD_FAST
只是访问第一个、第二个、第三个等局部变量,这是一个数组索引操作。
其他版本的 Python(例如 PyPy)可能能够优化访问全局变量,在这种情况下可能根本没有任何区别。
第一个代码(以n=i+const
作为循环体)反汇编为:
>>> dis.dis(A.lengthy_op)
5 0 LOAD_FAST 0 (self)
3 LOAD_ATTR 0 (const)
6 STORE_FAST 1 (const)
6 9 SETUP_LOOP 30 (to 42)
12 LOAD_GLOBAL 1 (xrange)
15 LOAD_GLOBAL 2 (AVOGADRO)
18 CALL_FUNCTION 1
21 GET_ITER
>> 22 FOR_ITER 16 (to 41)
25 STORE_FAST 2 (i)
8 28 LOAD_FAST 2 (i)
31 LOAD_FAST 1 (const)
34 BINARY_ADD
35 STORE_FAST 3 (n)
38 JUMP_ABSOLUTE 22
>> 41 POP_BLOCK
>> 42 LOAD_CONST 0 (None)
45 RETURN_VALUE
而第二个块给出:
>>> dis.dis(A.lengthy_op)
5 0 SETUP_LOOP 30 (to 33)
3 LOAD_GLOBAL 0 (xrange)
6 LOAD_GLOBAL 1 (AVOGADRO)
9 CALL_FUNCTION 1
12 GET_ITER
>> 13 FOR_ITER 16 (to 32)
16 STORE_FAST 1 (i)
7 19 LOAD_FAST 1 (i)
22 LOAD_GLOBAL 2 (const)
25 BINARY_ADD
26 STORE_FAST 2 (n)
29 JUMP_ABSOLUTE 13
>> 32 POP_BLOCK
>> 33 LOAD_CONST 0 (None)
36 RETURN_VALUE
Python 不会制作全局变量的本地副本,因为没有简单的方法可以确保在代码运行时全局值不会改变。 任何东西,甚至是另一个线程或调试器,都可以在循环执行时修改该值。
它是更快还是更慢实际上取决于您的范围,范围存储在字典中,字典越小,访问速度(略微)越快。 由于字典是作为哈希集实现的,因此查找性能是 O(1)。
每当您尝试访问变量时,Python 都会按以下顺序遍历范围:
globals()
访问)list
、 int
等。访问函数/类属性的工作方式类似,但涉及:
__getattribute__
__dict__
__getattr__
这也适用于所有继承的类。
邓肯完美地回答了您的其余问题
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.