Python:使用'yield from'时的奇怪行为`
在下面的代码中,我遇到了一个Python:使用'yield from'时的奇怪行为`,python,yield,Python,Yield,在下面的代码中,我遇到了一个递归错误:超过了最大递归深度 def unpack(given): for i in given: if hasattr(i, '__iter__'): yield from unpack(i) else: yield i some_list = ['a', ['b', 'c'], 'd'] unpacked = list(unpack(some_list)) 如果我使用so
递归错误:超过了最大递归深度
def unpack(given):
for i in given:
if hasattr(i, '__iter__'):
yield from unpack(i)
else:
yield i
some_list = ['a', ['b', 'c'], 'd']
unpacked = list(unpack(some_list))
如果我使用some_list=[1、[2、[3]]]
,这很好,但如果我尝试使用字符串,则不会
我怀疑我缺乏python方面的知识。感谢您的指导。字符串是无限可编辑的。即使只有一个字符的字符串也是可编辑的
因此,除非为字符串添加特殊处理,否则您将始终获得堆栈溢出:
def flatten(x):
try:
it = iter(x)
except TypeError:
yield x
return
if isinstance(x, (str, bytes)):
yield x
return
for elem in it:
yield from flatten(elem)
注意:使用hasattr(i,'.\u iter'.
不足以检查i
是否可迭代,因为还有其他方法可以满足迭代器协议。确定对象是否可iter的可靠方法是调用iter(obj)
字符串本身是可迭代的,它们迭代的对象是字符串<“a”中x的code>产生'a'
本身。试试一些列表=[];some_list.append(some_list);unpack=list(unpack(some_list))
查看深度大于1000的任何东西都可能发生这种情况。所以剩下的问题是为什么每个字符串的深度都大于1000,这是wim的回答(以及BallpointBen的评论)所解释的。@abarnert对于你的情况,是\uuu iter\uuuu
Forlist
返回它自己,自然是无止境的递归吗?@user7865286是的,或者更简单地说,列表包含它自己:某个列表[0]是一些列表
。我原以为这比如果s='a'
,s[0]是s
,这会有助于说明问题,但现在我想起来了,有多少人真正了解Python中的递归列表?唯一真正明显的例子是一个显式迭代自身的类,它太大,太分散注意力,不值得评论;最好像BallpointBen那样直接转到字符串的s[0]is s
。它可能只是一个注释。“使用hasattr(i,''.''.'''.'''.'''.'iter'.'
不足以检查i
是否可iterable”-true,但isinstance(x,iterable)
在许多相同的情况下都会失败。最可靠的检查是只需调用iter
@user2357112就可以了。特别是,“旧式序列迭代协议”(实际上是一对相关的不完整协议,但不要紧)不是由两个测试捕获的。只需定义一个带有\uu len\uuu
的类,该类返回int
(并确保它在范围内(0,1您认为实现扁平化
的更具python风格的方法是什么?我几乎总是喜欢EAFP,但不知何故,我总是回到LBYL来处理这个问题。例如,哪个异常要捕获,仅仅是TypeError
就足够了吗?很难说。isinstance(x,Iterable)
肯定是比hasattr(x,''uuuuu iter'uuuuu')
的一个改进。它将通过\uuuu iter\uuuuuuuu=None
获取“反注册”,并且它将在2中检测到isinstance(“asdf,Iterable)
(尽管只是由于寄存器
调用)。