Python |为什么访问实例属性的速度比本地速度慢? [英] Python | Why is accessing instance attribute slower than local?

查看:138
本文介绍了Python |为什么访问实例属性的速度比本地速度慢?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

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分解后的字节码,也可以看到f2f1要做的事情更多.

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屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆