Sco*_*ott 1 python namespaces class
我已经多次看到过,其中实例变量(例如obj_foo和obj_bar)被重新赋值为本地方法变量(例如,在内call):
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()
Run Code Online (Sandbox Code Playgroud)
我不确定这是否符合惯例(易于阅读)或是否有更重要的目的?
这是不好的做法吗?
这会影响性能吗?
通常,没有理由这样做,但在某些情况下可能是:
速度可能是这里更重要的因素.访问成员变量涉及各种机制(见__getattr__,__getattribute__,__dict__,描述这需要一些时间)来解决.此外,变量的getter可能会做更昂贵的事情.
在另一方面,局部变量是在CPython的编译时间进行了优化,所以实际上没有查找名为变量'obj_foo'的__dict__,而是解释只是挑选第一个局部变量,因为它知道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()
Run Code Online (Sandbox Code Playgroud)
时间几乎相同,但有一些不同:
>>> 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
Run Code Online (Sandbox Code Playgroud)
恕我直言,在这种情况下,差异几乎不足以证明添加一行代码是正确的.