【问题标题】:Designate a variable as a list without overwriting it in a function将变量指定为列表而不在函数中覆盖它
【发布时间】:2018-12-31 12:44:31
【问题描述】:

我创建了一个函数,它将嵌套列表展平为普通列表。

outputarray = []

def flattenarray(x):
    for elmt in x:
        if isinstance(elmt, float) or isinstance(elmt, int):
            outputarray.append(elmt)
        elif isinstance(elmt, list):
            flattenarray(elmt)
    return outputarray

上面的工作完美,但我试图在函数中使用“outputarray”变量,但是当我这样做时,递归步骤会将 outputarray 列表覆盖回一个空列表。

我怎样才能使这项工作在函数内指定一个列表,同时能够在递归期间附加到它而不覆盖它?

【问题讨论】:

    标签: python list recursion


    【解决方案1】:

    您需要在函数中创建输出数组。一种方法是在递归步骤中传递输出容器:

    def flattenarray(x, outputarray=None):
        if outputarray is None:
            outputarray = []
        for elmt in x:
            if isinstance(elmt, float) or isinstance(elmt, int):
                outputarray.append(elmt)
            elif isinstance(elmt, list):
                flattenarray(elmt, outputarray=outputarray)
        return outputarray
    

    更 Pythonic 的方法是让扁平化器一个接一个地生成项目。注意isinstance可以接受一个元组类型,所以你只需要调用一次。

    def flatten(x):
        for elmt in x:
            if isinstance(elmt, (int, float, str, bytes)):
                yield elmt
            else:
                yield from flatten(elmt)
    

    更正确的鸭子类型实现:

    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)
    

    【讨论】:

    • 感谢 wim - 对于您的第二个代码块,有没有办法在函数中返回输出?我知道当我尝试打印函数列表时您的代码有效,但想知道您是否可以在函数内执行所有操作。
    • 只需定义另一个函数,例如def flattenL(x): return list(flatten(x))
    【解决方案2】:

    这与单行函数完美配合,基本思想与wim相同:

    def flatten(lst, outputarray=[]):
        return sum( ([x] if not isinstance(x, (list,tuple))  else flatten(x)
                         for x in lst), outputarray)
    
    
    lst=[1,2,3,[2,4,5,[6]],(7,8,9)]
    
    print(flatten(lst))
    

    结果:

    [1, 2, 3, 2, 4, 5, 6, 7, 8, 9]
    

    【讨论】:

    • 这是对可变默认参数的危险使用。
    • @ juanpa.arrivillaga,是的,但它实际上适用于扁平化功能。
    • @juanpa.arrivillaga 你能解释一下原因吗?
    【解决方案3】:

    您可以使用递归函数调用的返回值来扩展输出,而不是尝试插入全局变量:

    def flattenarray(x):
        outputarray = []
        for elmt in x:
            if isinstance(elmt, float) or isinstance(elmt, int):
                outputarray.append(elmt)
            elif isinstance(elmt, list):
                outputarray.extend(flattenarray(elmt))
        return outputarray
    

    这会创建比严格必要的更多的临时列表,因此效率不高。另一方面,它与您的原始代码一样易于阅读。

    另一方面,我想建议对您的代码进行概括。无需检查三种特定类型并跳过其他所有内容,您只需检查元素是否可迭代:

    全局变量:

    def flattenarray(x):
        outputarray = []
        for elmt in x:
            try:
                outputarray.extend(flattenarray(elmt))
            except TypeError:
                # the error will be raised by the for loop in the recursive call
                outputarray.append(elmt)
        return outputarray
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2017-06-14
      • 1970-01-01
      • 2022-01-26
      • 2017-03-13
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多