Python中访问类变量的性能
我想知道在使用以下方法访问同一类的方法内部的类变量(dict)时,性能是否有任何差异:Python中访问类变量的性能,python,global-variables,scope,Python,Global Variables,Scope,我想知道在使用以下方法访问同一类的方法内部的类变量(dict)时,性能是否有任何差异: self.class_variable_dict.add(some_key, some_value) 及 显然,只要没有同名的实例变量,这两种方法都可以工作,但是有什么原因/用例我们应该选择一种而不是另一种吗?通过ClassName而不是通过self访问它会稍微快一点,因为如果您通过self访问它,它必须首先检查实例名称空间。但我并不认为这两者之间的差别有多大,除非你有分析信息表明这一点 因此,我建议使用你
self.class_variable_dict.add(some_key, some_value)
及
显然,只要没有同名的实例变量,这两种方法都可以工作,但是有什么原因/用例我们应该选择一种而不是另一种吗?通过
ClassName
而不是通过self
访问它会稍微快一点,因为如果您通过self
访问它,它必须首先检查实例名称空间。但我并不认为这两者之间的差别有多大,除非你有分析信息表明这一点
因此,我建议使用你认为作为人类更容易阅读/理解的方法
语义上,只有当class\u variable\u dict
变量被隐藏在某个地方时,它们才会有所不同——特别是,如果(a)self
定义了一个同名变量;或者(b)self
是ClassName
的子类的一个实例,并且该子类(或者它的一个基仍然是ClassName
的子类)定义了一个同名变量。如果两者都不是真的,那么它们在语义上应该是相同的
编辑:
德尔南有一个很好的观点:有一些因素可能会使两者更快。我坚持我的主张,除非是在一个非常非常紧密的循环中,否则差异将是微不足道的。为了测试它,我创建了我能想到的最紧密的循环,并用timeit
计时。结果如下:
- 通过类变量访问:20.226秒
- 通过仪表变量访问:23.121秒
import timeit
setup='''
class A:
var = {}
def f1(self):
x = A.var
def f2(self):
x = self.var
a = A()
'''
print 'access via class var: %.3f' % timeit.timeit('a.f1()', setup=setup, number=100000000)
print 'access via inst var: %.3f' % timeit.timeit('a.f2()', setup=setup, number=100000000)
让我们看看不同的选项都做了什么
In [1]: class Foo:
...: bar = {}
...:
In [2]: import dis
In [3]: dis.dis(lambda: Foo.bar.add(1,2))
1 0 LOAD_GLOBAL 0 (Foo)
3 LOAD_ATTR 1 (bar)
6 LOAD_ATTR 2 (add)
9 LOAD_CONST 1 (1)
12 LOAD_CONST 2 (2)
15 CALL_FUNCTION 2
18 RETURN_VALUE
In [4]: dis.dis(lambda: Foo().bar.add(1,2))
1 0 LOAD_GLOBAL 0 (Foo)
3 CALL_FUNCTION 0
6 LOAD_ATTR 1 (bar)
9 LOAD_ATTR 2 (add)
12 LOAD_CONST 1 (1)
15 LOAD_CONST 2 (2)
18 CALL_FUNCTION 2
21 RETURN_VALUE
从中可以看出,除了在第二种情况下创建对象之外,这两种样式都生成相同的字节码
另一方面,这并不重要。用最精确的方式表达你的目标。只有在速度重要时才进行优化 我建议只使用
ClassName.dict\u value[key]=value
这里也可以看到同样的问题,我在@Edward Loper test的基础上发布了一个更广泛的测试,包括比类变量更快的模块变量。如果你真的关心速度,那么显然你根本不把它放在类中,而是有一个模块全局_classname _dict_值,除了有人可以在您的模块作用域之外访问dict_值之外,没有其他好处。@senderle:字节码只是在实例化对象时有所不同。好的,谢谢您解决这个问题。但我仍然认为需要注意的是,相同的字节码并不一定会产生相同的性能。在这种情况下,LOAD_ATTR是一条字节码指令,但它可以更快或更慢,这取决于具体情况——相反,同一组cpu指令可能更快或更慢,这取决于是否存在缓存未命中。oth,查找
self
会更快,因为它是本地指令,因此可以从C数组访问,而ClassName
是一个全局变量,必须在dict中查找。除了评测之外,没有办法知道哪个更快!
In [1]: class Foo:
...: bar = {}
...:
In [2]: import dis
In [3]: dis.dis(lambda: Foo.bar.add(1,2))
1 0 LOAD_GLOBAL 0 (Foo)
3 LOAD_ATTR 1 (bar)
6 LOAD_ATTR 2 (add)
9 LOAD_CONST 1 (1)
12 LOAD_CONST 2 (2)
15 CALL_FUNCTION 2
18 RETURN_VALUE
In [4]: dis.dis(lambda: Foo().bar.add(1,2))
1 0 LOAD_GLOBAL 0 (Foo)
3 CALL_FUNCTION 0
6 LOAD_ATTR 1 (bar)
9 LOAD_ATTR 2 (add)
12 LOAD_CONST 1 (1)
15 LOAD_CONST 2 (2)
18 CALL_FUNCTION 2
21 RETURN_VALUE