python - 迭代期间运行时错误?

标签 python iteration

列表和集合之间的区别之一是列表可以在迭代期间更改 - 我们可以在循环中附加到它,等等。但是,如果我们尝试在 for 循环期间添加到集合,运行时出现错误。然而,Python 如何检测 set.add() 正在循环中使用,然后引发运行时错误?如果我尝试重新创建伪列表类并在类的追加函数中引发运行时错误,我是否只需重载 __iter__ 以防止任何追加?

举个例子:

a_set = {1,2,3,4}
a_list = [1,2,3,4]

for i in a_list:
     a_list.append(5)

这会导致无限循环

for j in a_set:
    a_set.add(5)

这会导致运行时错误。

它们都有 __iter__ 函数,所以在我的伪列表类中,我应该如何重载 __iter__ 以便它会像集合一样引发运行时错误?

最佳答案

进入 for 循环时,Python 首先对可迭代对象调用 iter 来获取或创建一个迭代器。然后,循环从迭代器中请求下一个项目,直到看到 StopIteration 异常(除非流程已通过 break 提前退出循环, return 语句,或其他一些异常)。 for 循环例如:

for element in iterable:
    ...

可以大致这样重写:

it = iter(iterable)
while True:
    try:
        element = next(it)
    except StopIteration:
        break
    ...

现在,通过使用列表实例作为可迭代对象,您将迭代与使用集合实例作为可迭代对象时不同的迭代器类型。/em>:

>>> iter([0])
<list_iterator at 0xcafef00d>
>>> iter({0})
<set_iterator at 0xdeadbeef>

set_iterator 类型和 list_iterator 类型以不同的方式实现__next__。这是setiter_iternext CPython 中的函数,其中 changing size is guarded againstlistiter_next没有这样的守卫。

我希望您现在可以了解如何直接在 Python 迭代器中创建类似的保护措施。当您定义__next__方法时,您可以检查大小是否已更改并引发:

class MyIterator:
    def __init__(self, obj):
        self.obj = obj  # note: you may prefer to use a weakref here
        self.it = iter(obj)
        self.initial_size = len(obj)
    def __iter__(self):
        return self
    def __next__(self):
        if len(self.obj) != self.initial_size:
            raise RuntimeError('changed size...doh!')
        return next(self.it)

class GrumpyList:
    def __init__(self, data):
        self.data = data
    def __iter__(self):
        return MyIterator(self.data)

演示:

>>> for i in g:
...     print(i)
...     if i == 2:
...         g.data.append(99)
...         
0
1
2
---------------------------------------------------------------------------
RuntimeError                              Traceback (most recent call last)
...
RuntimeError: changed size...doh!

关于python - 迭代期间运行时错误?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/50166773/

相关文章:

search - 二叉树搜索的迭代版本

javascript - 使用 "in"关键字迭代 Javascript 数组

python - 导入错误 : cannot import name 'get_default_renderer'

python - 连接表的多个列

python - 构建 Boost Python 调试

python - 使用 DBSCAN 时出现 "could not convert integer scalar"错误

javascript - 使用javascript数组创建MLM类型树结构

java - 遍历数组,android dev

python - 在 Python 中追加列表的说明和首选方法

javascript - Array.prototype.splice 的意外行为