2015-07-03 30 views
2

我们正在做一些实验来比较类和命名元组的访问时间,并观察奇怪的事情。为什么通过字段名访问namedtuple比访问类的成员变量慢?

import time 
from collections import namedtuple as namedtuple 

class myclass(object): 

    def __init__(self, _name, _dob, _value): 
    self.name = _name 
    self.dob = _dob 
    self.value = _value 

randomperson1 = myclass('randomperson', 10102000, 10.45) 

person = namedtuple('person', 'name dob value') 
randomperson2 = person('randomperson', 10102000, 10.45) 

在使用IPython中对于timeit,还观察到如下:

%timeit randomperson1.name,randomperson1.value,randomperson1.dob 
10000000 loops, best of 3: 125 ns per loop 

%timeit randomperson2.name,randomperson2.value,randomperson2.dob 
1000000 loops, best of 3: 320 ns per loop 

%timeit randomperson2[0],randomperson2[1],randomperson2[2] 
10000000 loops, best of 3: 127 ns per loop 

为什么的的字段名访问namedtuple比访问类的成员变量,以便慢得多?有什么办法可以加快速度吗?

+0

由于'namedtuple'需要执行字段名称查找?我的意思是,它必须在Python代码中进行查找,而不是在类似成员的解释器中进行查找。 –

+0

好的。这就说得通了。但是,如果一个namedtuple是不可变的,那么为什么应该动态完成这个查找?难道这不应该像一个班级那样完成吗? –

回答

3

这是因为在namedtuple属性name, value, dob不是实例的简单属性。他们实际上都变成了更复杂的东西

collections.py

_field_template = '''\ 
    {name} = _property(_itemgetter({index:d}), doc='Alias for field number {index:d}') 
''' 

例如

dob = property(itemgetter(2), doc='Alias for field number 2') 

因此,您可以看到其上还有其他图层。创建namedtuple的人决定以CPU效率为代价来保持内存效率的一致性。这就是原因。

这可以在创建自己的自定义类仿效这个很容易观察到:

from operator import itemgetter 

class CustomTuple(tuple): 
    my_attr = property(itemgetter(0)) 

test_tuple = CustomTuple([1]) 

现在衡量test_tuple.my_attr访问。你应该得到几乎相同的结果。