这是按引用调用的示例、错误还是其他原因?
Is this an example of call-by-reference, a bug, or something else?
我正在编写一个小程序来创建排列列表。我读到了 algorithm on wikipedia。
我的算法基本上采用最初排序的数字列表,并将其排列到位。然后它将这个新排列附加到列表中。找到所有排列后,它 returns 包含所有排列的列表列表。它非常擅长打印出预期的结果,但是当我尝试将这些结果添加到列表中时,事情变得有点有趣。
我注意到每次我找到下一个排列并将其附加到时,之前的列表元素都会更新为新的排列。所以,最后,返回的是一个列表,其中包含一堆相同排列的副本(恰好是最后一个排列)。
我读到 Python 是按值传递,按引用传递,我还读到两者都不是。我不够聪明,无法与这些人争论,但我想知道为什么我的程序会这样做,以及如何补救:
def lexi_order(nums):
permutations = []
length = len(nums)
while True:
# find largest index i such that nums[i] < nums[i + 1]
exists = False
for j, elem in enumerate(nums):
# check if last element
if j == length - 1:
break
if elem < nums[j + 1]:
i = j
exists = True
if not exists:
break
# find largest index k, such that i < k AND nums[i] < nums[k]
for j in range(i + 1, length):
if nums[j] > nums[i]:
k = j
# swap order of nums[i] and nums[k]
nums[i], nums[k] = nums[k], nums[i]
# reverse order of elements starting at position i+1
to_reverse = nums[i+1:][::-1]
nums[i+1::] = to_reverse
permutations.append(nums)
print(permutations)
return permutations
当您将 nums
附加到 permutations
时,您是在附加对它的引用,而不是复制所有数据。当你修改 nums
时,它到处都会被修改。 Python 通过引用传递。如果您对变量进行更改(不要与重新分配它混淆),该更改将反映在所有地方。
您在循环的每次迭代中就地修改输入 (nums
),然后不断向 permutations
添加对输入的引用。要修复它,请在循环开始时制作 nums
的副本,并在其中的所有地方使用它而不是原始文件。
您需要复制传递的 nums
,否则您正在处理传递的引用。例如
def lexi_order(nums):
permutations = []
nums = list(nums) # We are now working on a copy, and won't mutate the original whatsoever.
length = len(nums)
...
我正在编写一个小程序来创建排列列表。我读到了 algorithm on wikipedia。
我的算法基本上采用最初排序的数字列表,并将其排列到位。然后它将这个新排列附加到列表中。找到所有排列后,它 returns 包含所有排列的列表列表。它非常擅长打印出预期的结果,但是当我尝试将这些结果添加到列表中时,事情变得有点有趣。
我注意到每次我找到下一个排列并将其附加到时,之前的列表元素都会更新为新的排列。所以,最后,返回的是一个列表,其中包含一堆相同排列的副本(恰好是最后一个排列)。
我读到 Python 是按值传递,按引用传递,我还读到两者都不是。我不够聪明,无法与这些人争论,但我想知道为什么我的程序会这样做,以及如何补救:
def lexi_order(nums):
permutations = []
length = len(nums)
while True:
# find largest index i such that nums[i] < nums[i + 1]
exists = False
for j, elem in enumerate(nums):
# check if last element
if j == length - 1:
break
if elem < nums[j + 1]:
i = j
exists = True
if not exists:
break
# find largest index k, such that i < k AND nums[i] < nums[k]
for j in range(i + 1, length):
if nums[j] > nums[i]:
k = j
# swap order of nums[i] and nums[k]
nums[i], nums[k] = nums[k], nums[i]
# reverse order of elements starting at position i+1
to_reverse = nums[i+1:][::-1]
nums[i+1::] = to_reverse
permutations.append(nums)
print(permutations)
return permutations
当您将 nums
附加到 permutations
时,您是在附加对它的引用,而不是复制所有数据。当你修改 nums
时,它到处都会被修改。 Python 通过引用传递。如果您对变量进行更改(不要与重新分配它混淆),该更改将反映在所有地方。
您在循环的每次迭代中就地修改输入 (nums
),然后不断向 permutations
添加对输入的引用。要修复它,请在循环开始时制作 nums
的副本,并在其中的所有地方使用它而不是原始文件。
您需要复制传递的 nums
,否则您正在处理传递的引用。例如
def lexi_order(nums):
permutations = []
nums = list(nums) # We are now working on a copy, and won't mutate the original whatsoever.
length = len(nums)
...