11

次のように、キャッシングジェネレーターを使用して動的ディスパッチを実装するオブジェクトサブクラスがあります__ iter __(反復キャッシュを無効にするメソッドもあります)。

def __iter__(self):
    print("iter called")
    if self.__iter_cache is None:
        iter_seen = {}
        iter_cache = []
        for name in self.__slots:
            value = self.__slots[name]
            iter_seen[name] = True
            item = (name, value)
            iter_cache.append(item)
            yield item           
        for d in self.__dc_list:
            for name, value in iter(d):
                if name not in iter_seen:
                    iter_seen[name] = True
                    item = (name, value)
                    iter_cache.append(item)
                    yield item
        self.__iter_cache = iter_cache
    else:
        print("iter cache hit")
        for item in self.__iter_cache:
            yield item

うまくいっているようです...私が気づいていないかもしれない落とし穴はありますか? 私は何かばかげたことをしていますか?

4

4 に答える 4

7

container.__iter__()イテレータ オブジェクトを返します。イテレータ オブジェクト自体は、以下の 2 つのメソッドをサポートする必要があり、これらが一緒になってイテレータ プロトコルを形成します。

iterator.__iter__()

iterator オブジェクト自体を返します。

iterator.next()

コンテナから次のアイテムを返します。

それはまさにすべての発電機が持っているものです。したがって、副作用を恐れないでください。

于 2012-07-05T15:31:05.533 に答える
3

それは非常に脆弱なアプローチのようです。オブジェクトを一貫性のない状態にするには、アクティブな反復中に __slots、__dc_list、__iter_cache のいずれかを変更するだけで十分です。

反復中のオブジェクトの変更を禁止するか、一度にすべてのキャッシュ アイテムを生成してリストのコピーを返す必要があります。

于 2012-07-05T15:26:57.147 に答える
2

オブジェクトの反復を、オブジェクトが返す値のキャッシュから切り離したほうがよい場合があります。これにより、反復プロセスが簡素化され、キャッシュの実行方法や、キャッシュを有効にするかどうかなどを簡単に制御できるようになります。

考えられるもう 1 つの重要な考慮事項は、繰り返し処理されるオブジェクトがメソッドの連続する呼び出し間で変更される状況を、コードが予測的に処理しないという事実です。これに対処する簡単な方法の 1 つは、最初の呼び出しでキャッシュの内容を完全に入力し、次にyield呼び出しごとにキャッシュの内容だけを入力し、動作を文書化することです。

于 2012-07-05T16:09:44.193 に答える
0

あなたがしていることは、奇妙ではありますが有効です。a__slotsまたは__dc_list?? 一般に、オブジェクトの内容は、タイプではなく属性名で説明することをお勧めします(例:self.u_listではなくself.users)。

私のLazyPropertyデコレータを使用して、これを大幅に簡略化できます。

@LazyPropertyでメソッドを装飾するだけです。これが最初に呼び出され、デコレータが属性を結果に置き換えます。唯一の要件は、値が繰り返し可能であることです。可変状態には依存しません。また、self .__ iter_cacheを使用して、現在のコードにもその要件があります。

def __iter__(self)
    return self.__iter

@LazyProperty
def __iter(self)
    def my_generator():
        yield whatever
    return tuple(my_generator())
于 2012-07-05T16:37:19.120 に答える