这是按引用调用的示例、错误还是其他原因?

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)
    ...