Python 的迭代器解包star unpacking是如何实现的或者,解包自定义迭代器涉及哪些神奇的方法?

问题描述

我正在编写一个定义 __iter____len__ 的类,其中 __len__ 的值取决于 __iter__ 返回的迭代器。我得到了一个有趣的 RecursionError

语言版本:Python 3.8.6、3.7.6。 示例仅用于说明错误。

在以下示例中,Iter.__len__() 尝试解包 self,将结果存储在 list 中,然后尝试调用该列表上的内置 list.__len__()得到长度。

>>> class Iter:
...     def __iter__(self):
...         return range(5).__iter__()
...     def __len__(self):
...         return list.__len__([*self])
...
>>> len(Iter())
Traceback (most recent call last):
  File "<stdin>",line 1,in <module>
  File "<stdin>",line 5,in __len__
  File "<stdin>",in __len__
  [Previous line repeated 993 more times]
  File "<stdin>",line 3,in __iter__
RecursionError: maximum recursion depth exceeded in comparison

但是,如果我将类 Iter 定义如下,其中 Iter.__len__() 显式解包 Iter.__iter__() 返回的迭代器:

>>> class Iter:
...     def __iter__(self):
...         return range(5).__iter__()
...     def __len__(self):
...         return list.__len__([*self.__iter__()])
...
>>> len(Iter())
5

那么就没有错误了。

从回溯来看,似乎 list.__len__() 正在尝试调用 Iter.__len__(),甚至认为提供的参数应该已经是本机 list 对象。 RecursionError 的原因是什么?


根据schwobaseggl,使用set代替list不会导致RecursionError

>>> class Iter:
...     def __iter__(self):
...         return range(5).__iter__()
...     def __len__(self):
...         return set.__len__({*self})
...
>>> len(Iter())
5

解决方法

暂无找到可以解决该程序问题的有效方法,小编努力寻找整理中!

如果你已经找到好的解决方法,欢迎将解决方案带上本链接一起发送给小编。

小编邮箱:dio#foxmail.com (将#修改为@)