当前位置: 代码迷 >> python >> 你能解释一下这个功能吗?
  详细解决方案

你能解释一下这个功能吗?

热度:17   发布时间:2023-07-14 08:57:40.0
def a(n):
    return max([len(n)] + [a(i) for i in n]) if isinstance(n, list) else 0

这是我最近的一次测试,我无法让列表理解得失败。 所以基本上这个函数应该返回最大列表的长度(这是我假设基于正确的答案)我会理解,如果不是这部分函数:

+ [a(i) for i in n])

当我看到那个部分时,看起来它增加了迭代的列表长度。 有人可以阐明那部分的目的吗? 更具体地说,添加的原因。

编辑:所以仔细看之后......看起来函数将第一个列表的长度放在一个列表中,然后放下下一个列表的长度并返回最大值?...这是如何工作的?

此函数计算树中最大节点的长度(在列表中实现为列表)。 也许通过一些重命名和重新编写,它会更清楚:

def longest_list_in_tree(tree):
    if not isinstance(tree, list):
        return 0 # This is a leaf-value of the tree, it has "length 0"

    own_length = len(tree)
    longest_descendant_of_each_subtree = [
        longest_list_in_tree(subtree) for subtree in tree
    ]

    return max([own_length] + longest_descendant_of_each_subtree)

该程序的目标是在列表列表中找到最长列表的长度。 假设您将列表列表作为输入传递。

b = [[1], [1, 2], [3], [[1, 2, 3], [1]]]

现在,为了找到内部列表的长度,我们首先必须遍历当前列表。 但是如果初始输入本身不是列表呢? 我们将元素的长度返回为0.检查由此部分完成

... if isinstance(n, list) else 0

如果n不是list的实例,我们返回0.现在我们确定当前项是一个列表,我们得到这个列表len(n)的长度。 然后,我们遍历列表,就像这样

[a(i) for i in n]

我们得到n每个元素并递归调用a 现在,如果元素是一个列表, a(i)应该返回其中最长列表的长度。 因此,我们收集每个元素中最长列表的所有长度,将它们创建为列表并将其与n的长度连接起来。 这种连接完成了

[len(n)] + [a(i) for i in n]

我们通过用方括号括起来使len(n)成为一个列表, +运算符将追加我们从n所有元素得到的长度。 所以在每次递归的函数调用中,我们得到类似的东西

[length of current list,
        max length of sub elements in element 1 of n,
        max length of sub elements in element 2 of n,
        max length of sub elements in element 3 of n,
...
]

然后我们找到所有这些元素的最大值并将其返回给调用者。

为了更好地理解这个程序,我创建了一个装饰器来记录输入和相应的输出。 这可能有助于您更好地理解递归

def logger(f):
    def wrapper(args, level):
        print "\t\t" * level + "Entered with input ", args
        temp = f(args, level)
        print "\t\t" * level + "Leaving with length", temp
        return temp
    return wrapper

@logger
def a(n, lev):
    return max([len(n)] + [a(i, lev+1) for i in n]) if isinstance(n, list) else 0

b = [[1], [1, 2], [3], [[1, 2, 3], [1]]]

print a(b, 0)

而输出是

Entered with input  [[1], [1, 2], [3], [[1, 2, 3], [1]]]
        Entered with input  [1]
                Entered with input  1
                Leaving with length 0
        Leaving with length 1
        Entered with input  [1, 2]
                Entered with input  1
                Leaving with length 0
                Entered with input  2
                Leaving with length 0
        Leaving with length 2
        Entered with input  [3]
                Entered with input  3
                Leaving with length 0
        Leaving with length 1
        Entered with input  [[1, 2, 3], [1]]
                Entered with input  [1, 2, 3]
                        Entered with input  1
                        Leaving with length 0
                        Entered with input  2
                        Leaving with length 0
                        Entered with input  3
                        Leaving with length 0
                Leaving with length 3
                Entered with input  [1]
                        Entered with input  1
                        Leaving with length 0
                Leaving with length 1
        Leaving with length 3
Leaving with length 4
4

列表 推导是python和其他一些语言的相当深奥的属性。 它可能会让很多人感到困惑。 这就是说他们遵循的结构非常简单并且基于 :

  1. 表示输入列表成员的变量, 在这种情况下是递归函数调用。
  2. 在这种情况下要处理的列表n
  3. 可选的谓词表达式。
  4. 一个输出表达式,它根据输入列表中满足谓词的条目生成输出列表的条目。

在给定输入n该函数将返回最大的列表/子列表。 max函数调用中包含的列表推导构建了列表中所有值大小的列表(如果它不是列表,则为0),使用自身的递归调用以相同的方式遍历子列表。

为了帮助解释代码,您编写了另一个函数来返回传递给max函数调用的输入数组,以帮助您提高理解:

def b(n):
  return [len(n)]+[b(i) for i in n] if isinstance(n,list) else 0

例:

>>> x = [1,2,3,4,5,[1,2,3,4,5,6,7,8,9],7,[1,2,[1,2,3,4,5,6,7,8,9,10,11,12,13,14],4,5,6,[1,2]]]
>>> a(x)
14
>>> b(x)
[8, 0, 0, 0, 0, 0, [9, 0, 0, 0, 0, 0, 0, 0, 0, 0], 0, [7, 0, 0, [14, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0], 0, 0, 0, [2, 0, 0]]]

NB响应您的编辑 - +运算符允许您将两个列表合并在一起。 例如:

x = [a,b,c]
y = [d,e,f]
z = x + y;

让我为你打破这个:

def a(n):
    '''return the largest length of a list or sublists in that list'''
    if isinstance(n, list):
        # if n is a list, return the max of the len of the list
        # for all subitems in the list, perform a(subitem) recursively.
        # so if a sublist is longer than the list, return the largest len.
        return max([len(n)] + [a(i) for i in n]) 
    else:
        # that subitem isn't a list, so return 0, which won't factor into the max calc.
        return 0

我想我会称之为这样一个功能:

def max_len_list_of_lists(a_list):
    '''return the largest length of a list or sublists in that list'''
    ...

假设n是一个包含成员的列表,也可以是包含其他列表等的列表,这将返回最长列表的长度。 例如:

a([2,3,4,5]) = 4   # [2,3,4,5]
a([1, [2,3,4,5], 3]) = 4   # [2,3,4,5]
a([1, [2,3,4,5], [3, [7,8,9,0,1]]]) = 5   # [7,8,9,0,1]

基本上这是一个尾递归,表示所有列表的最大长度是作为输入传递的列表长度和作为列表的所有成员的最大长度。

用一些小例子运行它,看看为什么它成立。