我在使用自定義迭代器遍歷小容器時遇到了令人驚訝的性能差異。我希望有人能夠幫助我理解這些差異來自哪裏。自定義迭代器性能
首先是一些背景;我正在寫一些使用boost :: python的python擴展模塊,其中一個模塊包含一個綁定到實現getitem的3d float向量類型。因爲getitem有可能迭代它,但它看起來很慢,但它並不明顯,所以我決定在Python中使用一些簡單的自定義迭代器來更好地瞭解事情的工作原理。這也正是這些迭代器是從哪裏來的?
class MyIterator1(object):
__slots__ = ['values', 'popfn']
def __init__(self):
self.values = ['x', 'y', 'z']
self.popfn = self.values.pop
def __length_hint__(self):
return 3
def __iter__(self):
return self
def next(self):
try:
return self.popfn()
except IndexError:
raise StopIteration
class MyIterator2(object):
__slots__ = ['values', 'itfn']
def __init__(self):
self.values = ['x', 'y', 'z']
it = iter(self.values)
self.itfn = it.next
def __length_hint__(self):
return 3
def __iter__(self):
return self
def next(self):
return self.itfn()
class MyIterator3(object):
__slots__ = ['values', 'i']
def __init__(self):
self.values = ['x', 'y', 'z']
self.i = 0
def __length_hint__(self):
return 3
def __iter__(self):
return self
def next(self):
if self.i >= 3:
raise StopIteration
value = self.values[self.i]
self.i += 1
return value
def MyIterator4():
val = ['x', 'y', 'z']
yield val[0]
yield val[1]
yield val[2]
接下來,我通過與timeit模塊的腳本(假定上面的代碼是在一個模塊調用testiter)
import timeit
timer1 = timeit.Timer('r = list(testiter.MyIterator1())', 'import testiter')
timer2 = timeit.Timer('r = list(testiter.MyIterator2())', 'import testiter')
timer3 = timeit.Timer('r = list(testiter.MyIterator3())', 'import testiter')
timer4 = timeit.Timer('r = list(testiter.MyIterator4())', 'import testiter')
timer5 = timeit.Timer('r = list(iter(["x", "y", "z"]))', 'import testiter')
print 'list(testiter.MyIterator1())'
print timer1.timeit()
print "\n"
print 'list(testiter.MyIterator2())'
print timer2.timeit()
print "\n"
print 'list(testiter.MyIterator3())'
print timer3.timeit()
print "\n"
print 'list(testiter.MyIterator4())'
print timer4.timeit()
print "\n"
print 'list(iter(["x", "y", "z"]))'
print timer5.timeit()
此打印這些跑出以下
list(testiter.MyIterator1())
8.5735929
list(testiter.MyIterator2())
5.28959393501
list(testiter.MyIterator3())
6.11230111122
list(testiter.MyIterator4())
2.31263613701
list(iter(["x", "y", "z"]))
1.26243281364
不出所料蟒蛇的ListIterator是最快的,用相當的餘量。我認爲這是python中的一些魔術優化。生成器也比MyIterator類快得多,我再也沒有感到驚訝,並假設是由於所有工作都是在c中完成的,但這只是一個猜測。現在其他人更容易混淆/懇求。在這種情況下,嘗試/除外聲明看起來像是昂貴的還是別的什麼?
任何幫助解釋這些差異將不勝感激!對長期職位道歉。
您可以嘗試使用元組而不是['x','y','z'](如果可能):元組構造比列表快一點。 –