4

我想知道在使用以下方法访问同一类的方法中的类变量(字典)时,性能是否有任何差异:

self.class_variable_dict.add(some_key, some_value)

ClassName.class_variable_dict.add(some_key, some_value)

显然,只要没有同名的实例变量,两者都可以工作,但是有什么理由/用例我们应该更喜欢一个而不是另一个?

4

3 回答 3

6

通过ClassName而不是通过访问它self稍微快一些,因为如果您通过它访问self它必须首先检查实例命名空间。但我不认为差异会很显着,除非你有分析信息表明它是显着的。

因此,我建议使用您认为作为人类更容易阅读/理解的任何一种。

class_variable_dict从语义上讲,只有当变量在某处被遮蔽时,它们才会有所不同——特别是,如果 (a)self定义了一个同名的变量;或 (b)self是 的子类的实例ClassName,并且该子类(或其仍然是 的子类的基类之一ClassName)定义了同名的变量。如果这些都不正确,那么它们在语义上应该是相同的。

编辑:

delnam有一个很好的观点:有些因素可能会使两者都更快。我坚持我的断言,除非它处于非常紧密的循环中,否则差异将是微不足道的。为了测试它,我创建了我能想到的最紧凑的循环,并用timeit. 结果如下:

  • 通过类 var 访问: 20.226 秒
  • 通过 inst var 访问: 23.121 秒

基于多次运行,误差条看起来大约为 1 秒——即,这是一个统计上的显着差异,但可能不值得担心。这是我的测试代码:

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)
于 2012-05-22T14:08:29.697 回答
3

让我们看看不同的选项都有什么作用。

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_value[key] = value

于 2012-05-22T14:11:05.757 回答
0

Python 中的实例变量与类变量

另请参阅此处相同的问题,其中我发布了基于@Edward Loper 测试的更广泛的测试,包括模块变量以及比类变量更快的测试。

于 2018-10-12T10:35:33.747 回答