来自深层嵌套列表/元组的提取元素的递归函数

efs*_*see 2 python recursion nested python-3.x

我想编写一个从深层嵌套元组和列表中提取元素的函数,比方说我有这样的东西

l = ('THIS', [('THAT', ['a', 'b']), 'c', ('THAT', ['d', 'e', 'f'])])
Run Code Online (Sandbox Code Playgroud)

我想要一个没有'THIS'和'THAT'的平面列表:

list = ['a', 'b', 'c', 'd', 'e', 'f']
Run Code Online (Sandbox Code Playgroud)

这是我到目前为止所拥有的:

def extract(List):
    global terms
    terms = []
    for i in word:
        if type(i) is not str:
            extract(i)
        else:
            if i is not "THIS" and i is not "THAT":
                terms.append(i)
    return terms
Run Code Online (Sandbox Code Playgroud)

但我一直在接受list = ['d', 'e', 'f'],看起来terms = []循环后再次设置'c'.

aba*_*ert 6

你正在做terms = []函数的顶部,所以当然每次递归调用函数时,你都会terms=[]再次这样做.

最快的解决方案是编写一个简单的包装器:

def _extract(List):
    global terms
    for i in word:
        if type(i) is not str:
            _extract(i)
        else:
            if i is not "THIS" and i is not "THAT":
                terms.append(i)
    return terms

def extract(List):
    global terms
    terms = []
    return _extract(List)
Run Code Online (Sandbox Code Playgroud)

还有一件事:你不应该is用来测试字符串相等性(除非是非常非常特殊的情况).这测试它们在内存中相同的字符串对象.它会发生在这里,至少在CPython中(因为两个"THIS"字符串都是同一个模块中的常量 - 即使它们不是,它们也会被intern编辑) - 但这不是你想要依赖的东西.使用==,测试它们是否意味着相同的字符串,无论它们是否实际上是相同的对象.

测试身份类型更常用,但通常不是你想要的.实际上,您通常甚至不想测试类型是否相等.你通常不会有子类str- 但如果你这样做了,你可能想把它们视为str(因为这是子类型的全部要点).对于你经常进行子类化的类型来说,这一点更为重要.

如果你还没有完全理解所有这些,那么简单的指导就是永远不要使用,is除非你知道你有充分的理由.

所以,改变这个:

if i is not "THIS" and i is not "THAT":
Run Code Online (Sandbox Code Playgroud)

......对此:

if i != "THIS" and i != "THAT":
Run Code Online (Sandbox Code Playgroud)

或者,甚至可能更好(如果你有四个字符串要检查而不是两个,那肯定会更好),使用集合成员资格测试而不是and多个测试:

if i not in {"THIS", "THAT"}:
Run Code Online (Sandbox Code Playgroud)

同样,改变这个:

if type(i) is not str:
Run Code Online (Sandbox Code Playgroud)

......对此:

if not isinstance(i, str):
Run Code Online (Sandbox Code Playgroud)

但是,虽然我们在这里全部运作,为什么不使用闭包来消除全局?

def extract(List)
    terms = []
    def _extract(List):
        nonlocal terms
        for i in word:
            if not isinstance(i, str):
                _extract(i)
            else:
                if i not in {"THIS", "THAT"}:
                    terms.append(i)
        return terms
    return _extract(List)
Run Code Online (Sandbox Code Playgroud)

这不是我解决这个问题的方法(如果给出这个规范并告诉我用递归来解决它,那么我的答案可能是我要做的),但这有保留(和大部分的)精神的优点.实施)您现有的设计.

  • @efsee参见[wim的答案](/sf/answers/3447358631/),如果给出这个规范并要求递归地解决这个问题,这几乎就是我要做的事情. (2认同)