函数调用中的循环与显式列出所有参数之间的区别

Difference between a loop in a function call and listing all the arguments explicitly

我有一个函数可以按第一个列表对列表列表进行排序。当我像这样使用带有变量的函数时:

sort_lists(IN[0],IN[1],IN[2])

它工作得很好。虽然,因为我不知道我的输入包含多少列表,所以我想将其用作我的变量:

sort_lists(IN[idx] for idx in range(len(IN)))

尽管这 returns 是对一个列表(超级列表)的排序。为什么这些变量之间存在差异,我该如何改进代码?

这里是函数if decisive(这里IN[0]是带有多个子列表的输入):

def sort_lists(*args):
    zipped_list= zip(*sorted(zip(*args)))
    return [list(l) for l in zipped_list]

OUT = sort_lists(data_sort[0],data_sort[1],data_sort[2])

我想使用这个输出:

OUT = sort_lists(data_sort[idx] for idx in range(len(IN[0])))

只是将函数更改为接受列表列表,有问题吗?这段代码:

IN[idx] for idx in range(len(IN))

returns 再列表列表

这里有两点需要理解:

  • *args 会给你所有函数参数 as a tuple
  • IN[idx] for idx in range(len(IN)) 是一个 generator expression

如果您只需在函数中添加 print 语句,您就可以看到您的输入有何不同:

def sort_lists(*args):
    print(args)
    zipped_list= zip(*sorted(zip(*args)))
    return [list(l) for l in zipped_list]

令列表的输入列表为:lists = [[2, 1, 3], [1, 3, 4], [5, 4, 2]].

sort_lists(lists[0], lists[1], lists[2])

将打印:([2, 1, 3], [1, 3, 4], [5, 4, 2])。那是一个内部列表的元组。

不过,如果你这样称呼它:

sort_lists(lists[idx] for idx in range(len(lists)))

sort_lists(sublist for sublist in lists)

这将打印 (<generator object <genexpr> at 0x0000007001D3FBA0>,),一个生成器的单元素元组。

您可以通过仅接受一个参数使您的函数与生成器一起工作:

def sort_lists(arg):
    zipped_list= zip(*sorted(zip(*arg)))
    return [list(l) for l in zipped_list]

sort_lists(lists[idx] for idx in range(len(lists)))
# [[1, 2, 3], [3, 1, 4], [4, 5, 2]]

但我建议保留您的函数原样,unpack您的列表在您调用它的地方:

>>> sort_lists(*lists)
[[1, 2, 3], [3, 1, 4], [4, 5, 2]]

正如 Georgy 所指出的,区别在于参数是生成器还是列表。我还要指出,这是一个使用和练习map方法的机会。 map 对列表中的每个条目应用相同的函数。该函数可以是内置函数,例如 sorted.

list_a = [[2, 1, 3], [1, 3, 4], [5, 4, 2]]
sorted_list_a = list(map(sorted, list_a)) # sorted is the python built-in function
print(sorted_list_a)

Returns:

[[1, 2, 3], [1, 3, 4], [2, 4, 5]]

您会注意到,您必须将 map 传递给 list 函数,因为 map returns 是一个地图对象,所以您必须转它进入一个列表。

map documentation is here. And a good example of it is here.