やや怠惰に実装したプログラムに興味深いバグを見つけ、それを正しく理解しているかどうか疑問に思いました。短いバージョンでは、Pythonのheapq
実装は実際にはリストを並べ替えず、ヒープ中心の方法でリストを作成するだけです。具体的にはheapify()
、順序付けられた方法でリストの理解を容易にする順序付けられたリストになることを期待していました。
Pythonのドキュメントのように、優先度キューの例を使用します。
from heapq import heapify, heappush, heappop
from random import shuffle
class Item(object):
def __init__(self, name):
self.name = name
lst = []
# iterate over a pseudo-random list of unique numbers
for i in sample(range(100), 15):
it = Item("Some name for %i" % i)
heappush(lst, (i, it))
print([i[0] for i in lst])
結果は
>>> [2, 22, 7, 69, 32, 40, 10, 97, 89, 33, 45, 51, 94, 27, 67]
これは、リストの元の順序ではなく、ここで説明するヒープ中心の順序であることに注意してください。私はこれが完全に注文されることを怠惰に期待していました。
テストとして、heapify()を介してリストを実行しても、変更はありません(リストはすでにヒープのように順序付けられているため)。
heapify(lst)
print([i[0] for i in lst])
>>> [2, 22, 7, 69, 32, 40, 10, 97, 89, 33, 45, 51, 94, 27, 67]
関数を使用してリストを反復処理すると、heappop()
期待どおりの順序になります。
lst2 = []
while lst: lst2.append(heappop(lst))
print([i[0] for i in lst2])
>>> [2, 7, 10, 22, 27, 32, 33, 40, 45, 51, 67, 69, 89, 94, 97]
したがって、heapq
(少なくとも人間の意味では)リストを順序付けないように見えますが、heappush()
andheappop()
関数はヒープのように順序付けられたリストを取得できます。
結果:ヒープリストに対するスライスおよびリスト内包演算は、順序付けされていない結果になります。
これは本当ですか、そしてこれは常に本当ですか?
(BTW:WinXPシステム上のPython 3.0.1)