Python 自引用列表在排序时产生奇怪的输出

abh*_*asu 50 python list

我最近在尝试使用.sort()和对自引用列表进行排序时遇到了一个奇怪的差异sorted()。我希望有人能对此有所了解。有问题的代码如下:

lst = [1, 2, 3]

lst[0] = lst
lst[1] = lst
lst[2] = lst

print(lst)

print(sorted(lst))

lst.sort()

print(lst)
Run Code Online (Sandbox Code Playgroud)

上面的代码产生以下输出:

[[...], [...], [...]]
[[[...], [...], [...]], [[...], [...], [...]], [[...], [...], [...]]]
[[...], [...], [...]]
Run Code Online (Sandbox Code Playgroud)

它的输出print(sorted(lst))让我感到困惑。想知道是否是某种形式的递归导致了它?

Sil*_*olo 97

我要打电话给你的名单x,因为坦率地说,l看起来太像第一名了,让我失望了。所以你有一个x看起来像这样的列表

[x, x, x]
Run Code Online (Sandbox Code Playgroud)

现在,我们做

print(x)
Run Code Online (Sandbox Code Playgroud)

Python 足够聪明,可以说“嘿,看,这个列表递归地包含自己,我们不要在它自己内部再次打印它。” 所有地点都x出现在您的列表中,我们得到[...]

[[...], [...], [...]]
Run Code Online (Sandbox Code Playgroud)

现在考虑

x.sort()
print(x)
Run Code Online (Sandbox Code Playgroud)

我们对列表进行排序,这没什么用,因为每个元素都是相同的。然而,至关重要的是,这一切都发生在原地。列表开始看起来像[x, x, x],结束时看起来像[x, x, x]x我们的列表在哪里。所以打印看起来是一样的。

[[...], [...], [...]]
Run Code Online (Sandbox Code Playgroud)

最后,你有趣的例子。

sorted(x)
Run Code Online (Sandbox Code Playgroud)

sorted与 不同list.sort,它不会修改列表而是生成一个列表。让我们称这个新列表为y。在您的x.sort例子,到了最后,我们有相同的列表x,看起来像x = [x, x, x]。当我们打印列表时,我们立即看到递归并停止打印。

但是,sorted(x)会生成一个列表。该列表仍然看起来像[x, x, x],但它不是列表x。这是一个新列表y = [x, x, x]

现在,我们做

print(sorted(x))
Run Code Online (Sandbox Code Playgroud)

Python 会看到一个包含三个元素的列表:[x, x, x]. 我们看看这些元素中的每一个。我们要打印y,所以这个列表中包含的事实x不是一个递归问题; 它是一个非常普通的列表,其中包含其他列表。所以我们xy. 现在,再往下一层,我们看里面x,看到它x再次包含,你瞧。这一个递归问题,但它发生在一步之后,因为我们创建了一个新列表,尽管它看起来与原始列表相同,但又是不同的。

[[[...], [...], [...]], [[...], [...], [...]], [[...], [...], [...]]]
Run Code Online (Sandbox Code Playgroud)

  • @GrijeshChauhan:以大写字母开头的名称通常用于常量。 (27认同)
  • 常量或类;在任何情况下都不是变量,其约定是`snake_case`。我个人看到许多数据科学家和大学生特别反对这一点,这使得他们的代码更难阅读。 (6认同)
  • @theberzi:可以用任何语言编写 FORTRAN。:) (3认同)

J.G*_*.G. 5

也许你认为在lst[0] = lst那之后lst会是[[1,2,3],2,3]。如果是这样,您将假设 = lst 按 value 传递。但是列表是通过引用传递的,所以在这一点上lst[lst,2,3].

要通过值传递,使用lst[0] = list(lst)等,这时候右侧创建一个新的列表,用相同的值之前,但新的参考,因为在这种情况下list(lst)语法糖[v for v in lst]

正如@DeepSpace 所指出的,这个事实 aboutlist也解释了为什么print(list(lst))print(lst); 它打印[v for v in lst],这只是[lst, lst, lst].