2016-09-14 23 views
0

我讀通過Python文檔,並且,Section 8.4.1下, 我發現下面__init__定義(略):爲什麼要在__init__中聲明兩次列表?

class ListBasedSet(collections.abc.Set): 
    ''' Alternate set implementation favoring space over speed 
     and not requiring the set elements to be hashable. ''' 
    def __init__(self, iterable): 
     self.elements = lst = [] 
     for value in iterable: 
      if value not in lst: 
       lst.append(value) 

我不明白的部分是self.elements = lst = []線。爲什麼是雙重任務?

添加一些打印語句:

def __init__(self, iterable): 
    self.elements = lst = [] 
    print('elements id:', id(self.elements)) 
    print('lst id:', id(lst)) 
    for value in iterable: 
     if value not in lst: 
      lst.append(value) 

一個聲明:

ListBasedSet(range(3)) 
elements id: 4741984136 
lst id: 4741984136 
Out[36]: <__main__.ListBasedSet at 0x11ab12fd0> 

正如預期的那樣,它們都指向相同的PyObject。

簡潔是做這種事的唯一理由嗎?如果不是,爲什麼?與重入有關嗎?

+2

可能保存屬性l ookup – vaultah

+0

查找屬性需要花費嗎? – Ben

+1

python被解釋。並且地址必須被計算:對象地址+成員偏移量。如果您將參考預先計算爲局部變量,則不必這樣做。在這個邪惡的世界裏,沒有什麼是免費的 –

回答

0

我會說這是一個過早優化的情況;通過消除點,您不會節省那麼多,特別是對於大型輸入迭代;這裏的一些計時:

消除點:

%timeit ListBasedSet(range(3)) 
The slowest run took 4.06 times longer than the fastest. This could mean that an intermediate result is being cached. 
100000 loops, best of 3: 2.05 µs per loop 

%timeit ListBasedSet(range(30)) 
100000 loops, best of 3: 18.5 µs per loop 

%timeit ListBasedSet(range(3000)) 
10 loops, best of 3: 119 ms per loop 

雖然,用點(如更換lstself.elements

%timeit ListBasedSet(range(3)) 
The slowest run took 5.97 times longer than the fastest. This could mean that an intermediate result is being cached. 
100000 loops, best of 3: 2.48 µs per loop 

%timeit ListBasedSet(range(30)) 
10000 loops, best of 3: 22.8 µs per loop 

%timeit ListBasedSet(range(3000)) 
10 loops, best of 3: 118 ms per loop 

正如你可以看到,當我們增加的大小輸入迭代,時間差異幾乎消失,附加和成員資格測試幾乎涵蓋了任何收益。

+0

感謝您的基準! – Ben

相關問題