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
For
list
返回它自己,自然是无止境的递归吗?@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)
(尽管只是由于
寄存器
调用)。