Python迭代器类索引在for循环运行的第二次出现溢出
我定义了一个包含对象列表集合的类,并定义了Python迭代器类索引在for循环运行的第二次出现溢出,python,iterator,Python,Iterator,我定义了一个包含对象列表集合的类,并定义了\uuuuu iter\uuuuu和\uuuu next\uuuuu方法,使其成为可循环的。这里的集合是一个Deck类,它包含卡对象的列表 代码: 随机导入 班级卡: @静力学方法 def get_等级(): 回报率(“A”、“K”、“Q”、“J”、“10”、“9”、“8”、“7”、“6”、“5”、“4”、“3”、“2”)#A最高,2最低 @静力学方法 def get_suites(): 报税表(“H”、“D”、“S”、“C”) 定义初始(自我、套件、等
\uuuuu iter\uuuuu
和\uuuu next\uuuuu
方法,使其成为可循环的。这里的集合是一个Deck
类,它包含卡
对象的列表
代码:
随机导入
班级卡:
@静力学方法
def get_等级():
回报率(“A”、“K”、“Q”、“J”、“10”、“9”、“8”、“7”、“6”、“5”、“4”、“3”、“2”)#A最高,2最低
@静力学方法
def get_suites():
报税表(“H”、“D”、“S”、“C”)
定义初始(自我、套件、等级):
如果套件不在卡中。获取套件()
引发异常(“无效套件”)
如果等级不在卡中。获取等级()
引发异常(“无效秩”)
self.suite=suite
self.rank=等级
def\uuuu lt\uuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuu
self_-rank=卡。获取_-ranks()索引(self.rank)
card2_-rank=Card.get_-ranks()索引(card2.rank)
返回自我排名>卡片2排名
定义(自我,卡片2):
self_-rank=卡。获取_-ranks()索引(self.rank)
card2_-rank=Card.get_-ranks()索引(card2.rank)
返回自我排名>=card2排名
def\uuu gt\uuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuu
self_-rank=卡。获取_-ranks()索引(self.rank)
card2_-rank=Card.get_-ranks()索引(card2.rank)
返回自我等级
在运行时,我遇到以下错误:
我们有8H和KH
50张卡片:9H、8C、AC、7C、6H、2S、2D、5C、10H、5H、JS、5S、KD、JH、JC、QS、2H、3H、3S、3D、4C、4H、AD、KS、JD、QH、10D、6S、5D、8D、3C、6C、7D、AS、7H、AH、9S、10C、QC、QD、7S、2C、KC、8S、4D、4S、6D、10S、10S、9C
51张卡片:QS
[7D,5C,10H,QS]
52张卡片:10C
[KC,3S,9H,10C]
我们有2C和QD
回溯(最近一次呼叫最后一次):
文件“playing_cards.py”,第106行,在
印刷品(甲板)
文件“playing_cards.py”,第88行,在__
对于自助卡:
文件“playing_cards.py”,第73行,在下一个__
项目=自目录[自索引]
索引器:列表索引超出范围
在for循环的第二次运行中,当我将card对象推回到列表中时,情况似乎不一样。如何在保持弹出、推送功能的同时解决此问题
编辑:self.index
在第一次调用print()
后为50。当卡片被添加回列表时,索引保持在50,而牌组长度现在是51张。因此,在第二次(和第三次)打印调用中,将打印最后一张卡片,而不是整个卡片组。随后出现错误
我想我在这里读错了。我的问题是我应该在
StopIteration
位重置索引吗。这是正确的方法吗,还是索引应该自行重置?不确定您是如何到达的,但您超出了列表的长度。建议您比较列表的=
长度,如:
def __next__(self):
if self.index >= len(self.contents):
raise StopIteration
.....
我不知道你是怎么做到的,但你已经超出了你的名单。建议您比较列表的
=
长度,如:
def __next__(self):
if self.index >= len(self.contents):
raise StopIteration
.....
进行以下更改
def __iter__(self):
self.index = 0
return self
因此每次调用\uu iter\uu
,都会重置索引。
出现此错误的原因是,一旦您迭代了deck
,在迭代结束时,self.index==len(self.contents)
下次迭代时,self.index
应重置为0
我做了上述更改,它对我有效。做以下更改
def __iter__(self):
self.index = 0
return self
因此每次调用\uu iter\uu
,都会重置索引。
出现此错误的原因是,一旦您迭代了deck
,在迭代结束时,self.index==len(self.contents)
下次迭代时,self.index
应重置为0
我做了上述更改,它对我有效。注意:如果您试图通过实现自己的迭代器来学习迭代器的工作原理,那么上面的建议适用。如果您只想使您的数据组
更易于使用,您可以在数据组
中执行此操作:
def __iter__(self):
return self.contents # lists are already iterable
更妙的是,如果您希望您的数据组的行为类似于列表(迭代、索引、切片、删除),您可以扩展list
学习迭代器的工作原理:
这里的问题是将集合与迭代器合并。集合应包含一组项。您的Deck
是一个集合。集合是可编辑的,这意味着我可以对集合中的x执行。当我们对集合中的x执行时,Python实际上对iter(集合)
中的x执行,这将集合转换为迭代器
您希望迭代器和集合分开。如果集合是它自己的迭代器,那么一次只能有一个迭代器(它本身)。还要注意迭代器只能使用一次。通过在\uu iter\uuu
中执行self.index=0
,可以使迭代器(Deck
)可重用
考虑以下几点:
nums = [1, 2, 3]
for i in nums:
for j in nums:
print(i, j)
我们预计这种情况还会出现:
1 1
1 2
1 3
2 1
2 2
2 3
3 1
3 2
3 3
请注意,每次内部循环迭代整个集合时。如果nums
是它自己的迭代器,那么我们会遇到一些问题:
# Here internally nums sets the current index as 0
for i in nums:
# Here internally nums sets the current index as 0 again
for j in nums:
print(i, j)
# Once this inner loop finishes the current index is 4.
# But that is also the index for the outer loop, so the
# outer loop ends too
意外输出:
1 1
1 2
1 3
解决方案是Deck_
class Deck:
# ... snip ...
def __iter__(self):
return DeckIterator(self.contents)
class DeckIterator:
def __init__(self, cards):
self.index = 0
self.cards = cards
def __iter__(self):
return self
def __next__(self):
if self.index >= len(self.cards):
# We've gotten the end of the deck/list
raise StopIteration
item = self.cards[self.index]
self.index += 1
return item
class BadList(list):
def __iter__(self):
self._current_index = 0
return self
def __next__(self):
print(f'current index is {self._current_index}', end='')
if self._current_index >= len(self):
print(' which is the end, so ending iteration')
raise StopIteration
item = self[self._current_index]
print(f' so returning value {item}')
self._current_index += 1
return item
# Using letters instead of numbers so difference between indices
# and items is more clear
letters = BadList('abc')
for i in letters:
for j in letters:
print(i, j)
current index is 0 so returning value "a"
current index is 0 so returning value "a"
a a
current index is 1 so returning value "b"
a b
current index is 2 so returning value "c"
a c
current index is 3 which is the end, so ending iteration
current index is 3 which is the end, so ending iteration
if self.index >= len(self.contents):
class Deck:
def __init__(self):
self.contents = [Card(suite, rank)
for suite in Card.get_suites()
for rank in Card.get_ranks()]
random.shuffle(self.contents)
# no index here
def __iter__(self):
return DeckIterator(self)
# other methods, but no __next__
class DeckIterator:
def __init__(self, deck):
self.deck = deck
self.index = 0
def __iter__(self):
return self
def __next__(self):
if self.index > len(self.deck):
raise StopIteration
value = self.deck.contents[self.index]
self.index += 1
return value