2015-07-03 74 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訪問。你應該得到幾乎相同的結果。