Python |为什么访问实例属性的速度比本地速度慢? [英] Python | Why is accessing instance attribute slower than local?
问题描述
import timeit
class Hello():
def __init__(self):
self.x = 5
def get_local_attr(self):
x = self.x
# 10x10
x;x;x;x;x;x;x;x;x;x;
x;x;x;x;x;x;x;x;x;x;
x;x;x;x;x;x;x;x;x;x;
x;x;x;x;x;x;x;x;x;x;
x;x;x;x;x;x;x;x;x;x;
x;x;x;x;x;x;x;x;x;x;
x;x;x;x;x;x;x;x;x;x;
x;x;x;x;x;x;x;x;x;x;
x;x;x;x;x;x;x;x;x;x;
x;x;x;x;x;x;x;x;x;x;
def get_inst_attr(self):
# 10x10
self.x;self.x;self.x;self.x;self.x;self.x;self.x;self.x;self.x;self.x;
self.x;self.x;self.x;self.x;self.x;self.x;self.x;self.x;self.x;self.x;
self.x;self.x;self.x;self.x;self.x;self.x;self.x;self.x;self.x;self.x;
self.x;self.x;self.x;self.x;self.x;self.x;self.x;self.x;self.x;self.x;
self.x;self.x;self.x;self.x;self.x;self.x;self.x;self.x;self.x;self.x;
self.x;self.x;self.x;self.x;self.x;self.x;self.x;self.x;self.x;self.x;
self.x;self.x;self.x;self.x;self.x;self.x;self.x;self.x;self.x;self.x;
self.x;self.x;self.x;self.x;self.x;self.x;self.x;self.x;self.x;self.x;
self.x;self.x;self.x;self.x;self.x;self.x;self.x;self.x;self.x;self.x;
self.x;self.x;self.x;self.x;self.x;self.x;self.x;self.x;self.x;self.x;
if __name__ == '__main__':
obj = Hello()
print('Accessing Local Attribute:', min(timeit.Timer(obj.get_local_attr)
.repeat(repeat=5)))
print('Accessing Instance Attribute:', min(timeit.Timer(obj.get_inst_attr)
.repeat(repeat=5)))
我的计算机上的结果:
访问本地属性:0.686281020000024
Accessing Local Attribute: 0.686281020000024
访问实例属性:3.7962001440000677
Accessing Instance Attribute: 3.7962001440000677
为什么会这样?此外,在使用实例变量之前对它进行本地化是一种好习惯吗?
Why does this happen? Moreover, is it a good practice to localise the instance variable before using it?
推荐答案
每次python查找变量时,您都需要付出一点费用(LOAD_FAST
操作码).每次在现有对象上查找属性时,您需要支付的费用更多(LOAD_ATTR
操作码).例如
Every time python looks up a variable, you pay a little (LOAD_FAST
op code). Every time you look up an attribute on an existing object, you pay a little more (LOAD_ATTR
op code). e.g.
>>> def f1(self):
... x = self.x
... x
...
>>> def f2(self):
... self.x
... self.x
...
>>> dis.dis(f1)
2 0 LOAD_FAST 0 (self)
3 LOAD_ATTR 0 (x)
6 STORE_FAST 1 (x)
3 9 LOAD_FAST 1 (x)
12 POP_TOP
13 LOAD_CONST 0 (None)
16 RETURN_VALUE
>>> dis.dis(f2)
2 0 LOAD_FAST 0 (self)
3 LOAD_ATTR 0 (x)
6 POP_TOP
3 7 LOAD_FAST 0 (self)
10 LOAD_ATTR 0 (x)
13 POP_TOP
14 LOAD_CONST 0 (None)
17 RETURN_VALUE
>>>
即使您不知道如何阅读python分解后的字节码,也可以看到f2
比f1
要做的事情更多.
Even if you don't know how to read python disassembled bytecode, you can see that there is more stuff being done for f2
than for f1
.
此外,请注意,并非所有操作码都相同. LOAD_FAST
基本上是在本地范围内进行数组查找(因此顾名思义是FAST).另一方面, LOAD_ATTR
慢一点因为它会转换为通常进行字典查找的函数调用(__getattribute__
).
Also, note that not all op codes are the same. LOAD_FAST
is basically a array lookup in the local scope (so it is FAST as the name implies). LOAD_ATTR
is (on the other hand) a bit slower as it translates to a function call (__getattribute__
) that (usually) does a dictionary lookup.
就什么是最佳实践"而言,请阅读最容易的方法.我认为使用self
是非常习惯的,除非您通过避免使用self
可以显着提高性能,但是我认为这不是一个硬性规则.
As far as what is "best practice", do what reads the easiest. I think that it's pretty customary to use self
unless you demonstrate that there is a noticeable performance gain by avoiding it, but I don't think that is a hard rule.
这篇关于Python |为什么访问实例属性的速度比本地速度慢?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!