Skip to main content
 首页 » 编程设计

python之将实例变量重新分配给本地方法变量

2025年05月04日16www_RR

我已经多次看到下面的实例变量(例如 obj_foo 和 obj_bar)被重新分配为局部方法变量(例如在 调用):

class Example: 
    def __init__(self, obj_foo, obj_bar): 
        self.obj_foo = obj_foo 
        self.obj_bar = obj_bar 
 
    def call(self): 
        obj_foo, obj_bar = self.obj_foo, self.obj_bar 
 
        obj_foo.do_something() 
        obj_bar.do_something_else() 

我不确定这是惯例(易于阅读)还是有更重要的目的?

这是不好的做法吗?

这会影响性能吗?

请您参考如下方法:

通常,没有理由这样做,但在某些情况下可能是:

  • 更快(因为访问局部变量很快)
  • 更易于阅读(因为它更短)

速度可能是这里更重要的因素。访问成员变量涉及各种机制(参见 __getattr__ 、 __getattribute__ 、 __dict__ 、 descriptors )需要一些时间来解决。此外,变量的 getter 可能会做一些更昂贵的事情。

另一方面,局部变量在 CPython 中是在编译时优化的,所以实际上没有在 __dict__ 中查找名为 'obj_foo' 的变量,但是相反,解释器只选择第一个局部变量,因为它知道 obj_foo 是第一个局部变量而无需搜索名称。

因此,如果一个成员变量在同一函数中多次使用,并且分析显示访问该成员变量需要花费大量时间,那么使用局部变量可能会很有用。


通常,这并没有太大的区别,但这里有一个例子来说明这个想法:

class A: 
    def __init__(self,x): 
        self.x=x 
 
    def f(self): 
        for i in range(100): 
            self.x() 
 
class B: 
    def __init__(self,x): 
        self.x=x 
 
    def f(self): 
        x=self.x 
        for i in range(100): 
            x() 

时间几乎相同,但有一些不同:

>>> timeit.timeit('a.f()', setup='a=A(lambda:None)', globals=locals()) 
13.119033042000638 
>>> 
>>> timeit.timeit('b.f()', setup='b=B(lambda:None)', globals=locals()) 
10.219889547632562 

恕我直言,在这种情况下,差异几乎不足以证明添加一行代码是合理的。