亚洲在线久爱草,狠狠天天香蕉网,天天搞日日干久草,伊人亚洲日本欧美

為了賬號安全,請及時綁定郵箱和手機立即綁定
已解決430363個問題,去搜搜看,總會有你想問的

在python迭代器中根據條件選擇其他迭代器

在python迭代器中根據條件選擇其他迭代器

不負相思意 2023-06-06 17:24:43
在 python 中,我有一個迭代器返回一個固定范圍內的無限索引字符串,[0, N]稱為Sampler. 實際上我有一個列表,它們所做的只是返回范圍內的索引[0, N_0], [N_0, N_1], ..., [N_{n-1}, N_n].我現在要做的是首先根據范圍的長度選擇這些迭代器中的一個,所以我有一個weights列表[N_0, N_1 - N_0, ...],我選擇其中一個:    iterator_idx = random.choices(range(len(weights)), weights=weights/weights.sum())[0]接下來,我想要做的是創建一個迭代器,它隨機選擇一個迭代器并選擇一批M樣本。class BatchSampler:    def __init__(self, M):        self.M = M        self.weights = [weight_list]        self.samplers = [list_of_iterators]        ]        self._batch_samplers = [            self.batch_sampler(sampler) for sampler in self.samplers        ]    def batch_sampler(self, sampler):        batch = []        for batch_idx in sampler:            batch.append(batch_idx)            if len(batch) == self.M:                yield batch        if len(batch) > 0:            yield batch    def __iter__(self):        # First select one of the datasets.        iterator_idx = random.choices(            range(len(self.weights)), weights=self.weights / self.weights.sum()        )[0]        return self._batch_samplers[iterator_idx]問題在于它似乎iter()只被調用一次,所以只iterator_idx選擇了第一次。顯然這是錯誤的......解決這個問題的方法是什么?當您在 pytorch 中有多個數據集時,可能會出現這種情況,但您只想從其中一個數據集中采樣批次。
查看完整描述

1 回答

?
ibeautiful

TA貢獻1993條經驗 獲得超6個贊

在我看來,您想定義自己的容器類型。
我嘗試提供一些標準方法的示例
(希望不會遺漏太多細節);
您應該能夠將這些簡單示例之一重用
到您自己的課程中。


僅使用 __getitem__ (支持索引和循環):

對象.__getitem__

被調用以執行對自我[key]的評估。

class MyContainer:

? def __init__(self, sequence):

? ? self.elements = sequence? # Just something to work with.

??

? def __getitem__(self, key):

? ? # If we're delegating to sequences like built-in list,?

? ? # invalid indices are handled automatically by them?

? ? # (throwing IndexError, as per the documentation).

? ? return self.elements[key]


t = (1, 2, 'a', 'b')

c = MyContainer(t)

elems = [e for e in c]

assert elems == [1, 2, 'a', 'b']

assert c[1:-1] == t[1:-1] == (2, 'a')

使用迭代器協議:

對象.__iter__

object.__iter__(self)
當容器需要迭代器時調用此方法。此方法應返回一個新的迭代器對象,該對象可以迭代容器中的所有對象。對于映射,它應該遍歷容器的鍵。
迭代器對象也需要實現這個方法;他們必須自己返回。有關迭代器對象的更多信息,請參閱迭代器類型。

迭代器類型

container.__iter__()
返回一個迭代器對象。該對象需要支持下面描述的迭代器協議。

迭代器對象本身需要支持以下兩種方法,它們共同構成了迭代器協議:

iterator.__iter__()
返回迭代器對象本身。這是允許容器和迭代器與 for 和 in 語句一起使用所必需的。

iterator.__next__()
從容器中返回下一個項目。如果沒有其他項目,則引發 StopIteration 異常。

一旦迭代器的 __next__() 方法引發 StopIteration,它必須在后續調用中繼續這樣做。


class MyContainer:

? class Iter:

? ? def __init__(self, container):

? ? ? self.cont = container

? ? ? self.pos = 0

? ? ? self.len = len(container.elements)

? ??

? ? def __iter__(self): return self

? ? def __next__(self):

? ? ? if self.pos == self.len: raise StopIteration

? ? ? curElem = self.cont.elements[self.pos]

? ? ? self.pos += 1

? ? ? return curElem

??

? def __init__(self, sequence):

? ? self.elements = sequence? # Just something to work with.

??

? def __iter__(self):

? ? return MyContainer.Iter(self)


t = (1, 2, 'a', 'b')

c = MyContainer(t)

elems = [e for e in c]

assert elems == [1, 2, 'a', 'b']

使用發電機:

發電機類型

Python 的生成器提供了一種實現迭代器協議的便捷方式。如果一個容器對象的iter?() 方法被實現為一個生成器,它將自動返回一個迭代器對象(技術上,一個生成器對象)提供 iter?(?) 和next?() 方法。

發電機

返回生成器迭代器的函數。它看起來像一個普通函數,只是它包含 yield 表達式,用于生成一系列可在 for 循環中使用的值,或者可以使用 next() 函數一次檢索一個值。
通常指代生成器函數,但在某些情況下可能指代生成器迭代器。

生成器迭代器

由生成器函數創建的對象。

6.2.9.?產量表達式

在函數體中使用 yield 表達式會使該函數成為生成器


class MyContainer:

? def __init__(self, sequence):

? ? self.elements = sequence? # Just something to work with.

??

? def __iter__(self):

? ? for e in self.elements: yield e


t = (1, 2, 'a', 'b')

c = MyContainer(t)

elems = [e for e in c]

assert elems == [1, 2, 'a', 'b']


查看完整回答
反對 回復 2023-06-06
  • 1 回答
  • 0 關注
  • 171 瀏覽
慕課專欄
更多

添加回答

舉報

0/150
提交
取消
微信客服

購課補貼
聯系客服咨詢優惠詳情

幫助反饋 APP下載

慕課網APP
您的移動學習伙伴

公眾號

掃描二維碼
關注慕課網微信公眾號