在我开始之前:
import sys
sys.ps1 = "<?>> "
行。 作为一名C级程序员,我不禁以任何方式保持敏锐(使用我选择的任何语言),而是通过编写低级程序。今天,一个问题来自于Python3中一个非常简单的例子。
当一个小的pop()写入Stack类时,我收到了一些好奇的输出。
class Stack():
def __init__(self, data):
self.stack = [i for i in data]
self.size = int(len(self.stack))
def pop(self):
ch = self.stack[self.size - 1]
del(self.stack[-1])
self.size = self.size - 1
return ch
msg = Stack("Hello!")
for i in msg.stack:
print(m.pop(), end="")
<?>> !ol
for i in msg.stack:
print(m.pop(), end="")
<?>> le
for i in msg.stack:
print(m.pop(), end="")
<?>> H
print(msg.stack)
<?>> []
如你所见,弹出并输出整个列表需要3个循环['H','e','l','l','o']; 3个字符,然后是2个,然后是1个,但列表会相应耗尽吗?更长的输入需要更多的循环。这里有什么抑制因素?
答案 0 :(得分:2)
问题基本上是您在修改容器时迭代容器。可以这样考虑,在内部,list
迭代器只是继续推进索引,直到它达到IndexError
。由于您修改了列表,因此它会在您删除3个元素之后点击IndexError
,因为它会尝试my_list[3]
但len(my_list) == 3
。有几种方法可以解决这个问题。第一种,在这种情况下只使用while循环:
In [4]: class Stack:
...:
...: def __init__(self, data):
...: self.stack = [i for i in data]
...: self.size = int(len(self.stack))
...:
...: def pop(self):
...: ch = self.stack[self.size - 1]
...: del(self.stack[-1])
...: self.size = self.size - 1
...: return ch
...: def __len__(self):
...: return self.size
...:
In [5]: stack = Stack("Hello!")
In [6]: while stack:
...: print(stack.pop(), end='')
...:
!olleH
注意,我定义了__len__
方法,以便while stack:
可以直接使用,而不是while stack.size:
你也可以想象一下,只需在范围对象上循环:
In [7]: stack = Stack("Hello!")
In [8]: for _ in range(len(stack)):
...: print(stack.pop(), end='')
...:
!olleH
更棘手:在反向方向循环!由于您从最后开始弹出,因此IndexError
开始在list_reverseiterator
开始编制索引,直到alist[len(alist) - 1]
为止,因此您无法获得alist[0]
。我可能不会依赖这种行为感到舒服,但它有记录,并且确实有效:
In [9]: stack = Stack("Hello!")
In [10]: for _ in reversed(stack.stack):
...: print(stack.pop(), end='')
...:
!olleH
In [11]:
最后,尝试并且真实:循环副本:
In [11]: stack = Stack("Hello!")
In [12]: for _ in stack.stack[:]: #whole slice copies
...: print(stack.pop(), end='')
...:
!olleH