2

Python で非常に奇妙な動作に遭遇しました。から派生したクラスを使用するUserDictと、反復子a.items()は for ループで とは異なる動作をしますがa.data.items()、2 つが同一であっても:

Python 3.3.1 (default, Apr 17 2013, 22:32:14) 
[GCC 4.7.3] on linux
Type "help", "copyright", "credits" or "license" for more information.
>>> from datastruct import QueueDict
>>> a=QueueDict(maxsize=1700)
>>> for i in range(1000):
...     a[str(i)]=1/(i+1)
... 
>>> a.items()
ItemsView(OrderedDict([('991', 0.0010080645161290322), ('992', 0.0010070493454179255), ('993', 0.001006036217303823), ('994', 0.0010050251256281408), ('995', 0.001004016064257028), ('996', 0.0010030090270812437), ('997', 0.001002004008016032), ('998', 0.001001001001001001), ('999', 0.001)]))
>>> a.data.items()
ItemsView(OrderedDict([('991', 0.0010080645161290322), ('992', 0.0010070493454179255), ('993', 0.001006036217303823), ('994', 0.0010050251256281408), ('995', 0.001004016064257028), ('996', 0.0010030090270812437), ('997', 0.001002004008016032), ('998', 0.001001001001001001), ('999', 0.001)]))
>>> a.items()==a.data.items()
True
>>> # nevertheless:
... 
>>> for item in a.items(): print(item)
... 
('992', 0.0010070493454179255)
>>> for item in a.data.items(): print(item)
... 
('993', 0.001006036217303823)
('994', 0.0010050251256281408)
('995', 0.001004016064257028)
('996', 0.0010030090270812437)
('997', 0.001002004008016032)
('998', 0.001001001001001001)
('999', 0.001)
('991', 0.0010080645161290322)
('992', 0.0010070493454179255)
>>> 

クラス定義は次のとおりです。

import collections, sys

class QueueDict(collections.UserDict):

    def __init__(self, maxsize=1*((2**10)**2), *args, **kwargs ):
        self._maxsize=maxsize
        super().__init__(*args, **kwargs)
        self.data=collections.OrderedDict(self.data)

    def __getitem__(self, key):
        self.data.move_to_end(key)
        return super().__getitem__(key)

    def __setitem__(self, key, value):
        super().__setitem__(key, value)
        self._purge()

    def _purge(self):
        while sys.getsizeof(self.data) > self._maxsize:
            self.data.popitem(last=False)

これはかなり気がかりです。同じオブジェクトが[「視覚的な」検査と によって(a.items()==a.data.items()) == True]どのように動作するのか、またその理由は何ですか?

あなたの助けとアイデアをありがとう!

4

1 に答える 1

2

反復中にコレクションを変更すると、予期しない結果が生じる可能性があります (この場合はあります)。

あなたのゲッター;

def __getitem__(self, key):
    self.data.move_to_end(key)
    return super().__getitem__(key)

a.items...現在のキーをコレクションの最後に移動すると、コレクションの最後に到達したと見なされるため、for ループが停止します。

行にコメントを付けるとmove_to_end、反復を期待どおりに実行できます。

を反復処理しているときa.data.items、ゲッターは呼び出されないため、問題はありません。

于 2013-08-20T11:31:06.770 に答える