python - 将实例变量重新分配给局部方法变量
问题描述
我多次看到以下情况,其中实例变量(例如obj_foo
和obj_bar
)被重新分配为局部方法变量(例如 within 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()
我不确定这是惯例(易于阅读)还是有更重要的目的?
这是不好的做法吗?
这会影响性能吗?
解决方案
通常,没有理由这样做,但在某些情况下可能是:
- 更快(因为访问局部变量很快)
- 更容易阅读(因为它更短)
速度可能是这里更重要的因素。访问成员变量涉及需要一些时间来解决的各种机制(请参阅__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()
时间几乎相同,但有一些区别:
>>> 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
恕我直言,在这种情况下,差异几乎不足以证明添加那一行代码是合理的。
推荐阅读
- telegram - 电报即时视图模板
- mysql - 我正在尝试从 pyspark 访问 mysql 表。我正在尝试使用:
- python-3.x - Beautiful Soup Login with Python 3 - 这个表单的 POST url 是什么?
- python - 有没有办法让熊猫从用户选择的 excel 表中构建数据框?
- javascript - 如何将多个文件选择放入一个数组中,然后输出到 HTML
- javascript - 运行应用程序时出现 Sequelize index has been exist 错误
- linux - 如何使用 find、ls 命令根据数组中的条目显示文件名?
- java - 使用 ADAL4J 的 OneDrive 身份验证
- python - Python - 解析 DAX 表达式并识别表和字段
- javascript - 为什么 isNaN(undefined) !== Number.isNaN(undefined) 是真的