Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/python/286.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
在Python中,为什么局部变量访问比类成员访问快?_Python_Performance_Benchmarking - Fatal编程技术网

在Python中,为什么局部变量访问比类成员访问快?

在Python中,为什么局部变量访问比类成员访问快?,python,performance,benchmarking,Python,Performance,Benchmarking,在试图解决一个更复杂的问题时,我比较了局部变量和成员变量的访问速度 这里有一个测试程序: #!/usr/bin/env python MAX=40000000 class StressTestMember(object): def __init__(self): self.m = 0 def do_work(self): self.m += 1 self.m *= 2 class StressTestLocal(object

在试图解决一个更复杂的问题时,我比较了局部变量和成员变量的访问速度

这里有一个测试程序:

#!/usr/bin/env python

MAX=40000000

class StressTestMember(object):
    def __init__(self):
        self.m = 0

    def do_work(self):
        self.m += 1
        self.m *= 2

class StressTestLocal(object):
    def __init__(self):
        pass

    def do_work(self):
        m = 0
        m += 1
        m *= 2

# LOCAL access test
for i in range(MAX):
    StressTestLocal().do_work()

# MEMBER access test
for i in range(MAX):
    StressTestMember().do_work()
我知道在每次迭代中实例化
StressTestMember
StressTestLocal
看起来可能不是个好主意,但在建模程序中,这些基本上是活动记录,这是有意义的

在一个简单的基准之后

  • 本地访问测试:0m22.836
  • 成员访问测试:0m32.648s

本地版本在仍然是类的一部分的情况下,速度提高了约33%。为什么?

本地名称更快,因为Python进行了一些优化,使本地名称不需要dict访问,另一方面,实例属性需要访问对象的
\uu dict\ucode>


这也是为什么本地名称比全局名称快的原因。

本地名称更快,因为Python进行了一些优化,使本地名称不需要dict访问,另一方面,实例属性需要访问对象的
\uuu dict\uu


这也是为什么局部名称比全局名称快的原因。

self.m+=1
意味着您必须查找名为
self
的局部变量,然后找到名为
m

当然,如果你只需要查找一个局部变量,不需要额外的步骤,它会更快

查看发动机罩下发生的情况可能很有用:

>>> import dis
>>> dis.dis(StressTestLocal.do_work)
 18           0 LOAD_CONST               1 (0)
              3 STORE_FAST               1 (m)

 19           6 LOAD_FAST                1 (m)
              9 LOAD_CONST               2 (1)
             12 INPLACE_ADD         
             13 STORE_FAST               1 (m)

 20          16 LOAD_FAST                1 (m)
             19 LOAD_CONST               3 (2)
             22 INPLACE_MULTIPLY    
             23 STORE_FAST               1 (m)
             26 LOAD_CONST               0 (None)
             29 RETURN_VALUE        
>>> dis.dis(StressTestMember.do_work)
 10           0 LOAD_FAST                0 (self)
              3 DUP_TOP             
              4 LOAD_ATTR                0 (m)
              7 LOAD_CONST               1 (1)
             10 INPLACE_ADD         
             11 ROT_TWO             
             12 STORE_ATTR               0 (m)

 11          15 LOAD_FAST                0 (self)
             18 DUP_TOP             
             19 LOAD_ATTR                0 (m)
             22 LOAD_CONST               2 (2)
             25 INPLACE_MULTIPLY    
             26 ROT_TWO             
             27 STORE_ATTR               0 (m)
             30 LOAD_CONST               0 (None)
             33 RETURN_VALUE        

self.m+=1
意味着您必须查找名为
self
的局部变量,然后找到名为
m

当然,如果你只需要查找一个局部变量,不需要额外的步骤,它会更快

查看发动机罩下发生的情况可能很有用:

>>> import dis
>>> dis.dis(StressTestLocal.do_work)
 18           0 LOAD_CONST               1 (0)
              3 STORE_FAST               1 (m)

 19           6 LOAD_FAST                1 (m)
              9 LOAD_CONST               2 (1)
             12 INPLACE_ADD         
             13 STORE_FAST               1 (m)

 20          16 LOAD_FAST                1 (m)
             19 LOAD_CONST               3 (2)
             22 INPLACE_MULTIPLY    
             23 STORE_FAST               1 (m)
             26 LOAD_CONST               0 (None)
             29 RETURN_VALUE        
>>> dis.dis(StressTestMember.do_work)
 10           0 LOAD_FAST                0 (self)
              3 DUP_TOP             
              4 LOAD_ATTR                0 (m)
              7 LOAD_CONST               1 (1)
             10 INPLACE_ADD         
             11 ROT_TWO             
             12 STORE_ATTR               0 (m)

 11          15 LOAD_FAST                0 (self)
             18 DUP_TOP             
             19 LOAD_ATTR                0 (m)
             22 LOAD_CONST               2 (2)
             25 INPLACE_MULTIPLY    
             26 ROT_TWO             
             27 STORE_ATTR               0 (m)
             30 LOAD_CONST               0 (None)
             33 RETURN_VALUE        

因此,在局部范围内创建对类变量的新引用是否明智?e、 例如,
m=self.m
?在这个测试中不会有任何区别,但我的
do_work()
版本是一个运行数百万次的循环。@JamesS,如果它足够重要,那么最好测量您的确切用例来调整它。如果您多次引用
self.m
,我希望能够更快地引入局部变量。记住,如果您对其进行了变异,请将局部变量保存回属性。因此,在局部范围中创建对类变量的新引用是否明智?e、 例如,
m=self.m
?在这个测试中不会有任何区别,但我的
do_work()
版本是一个运行数百万次的循环。@JamesS,如果它足够重要,那么最好测量您的确切用例来调整它。如果您引用了几次
self.m
,我希望将其拉入局部变量会更快。记住,如果您对其进行了变异,请将局部变量保存回属性。