关于传递引用:在python中传递值

Passing values in Python

本问题已经有最佳答案,请猛点这里访问。

当您将一个像list、array这样的集合传递给python中的另一个函数时,它是复制它,还是仅仅是一个指针?


python按值传递对对象的引用。

Python passes references-to-objects by
value (like Java), and everything in
Python is an object. This sounds
simple, but then you will notice that
some data types seem to exhibit
pass-by-value characteristics, while
others seem to act like
pass-by-reference... what's the deal?

It is important to understand mutable
and immutable objects. Some objects,
like strings, tuples, and numbers, are
immutable. Altering them inside a
function/method will create a new
instance and the original instance
outside the function/method is not
changed. Other objects, like lists
and dictionaries are mutable, which
means you can change the object
in-place. Therefore, altering an
object inside a function/method will
also change the original object
outside.


问题是,整个引用/值概念不适合Python。python没有变量的"value"。python只有引用对象的对象和名称。

因此,当您调用一个函数并在圆括号内放置一个"名称"时,如下所示:

1
2
3
4
def func(x): # defines a function that takes an argument
    ... # do something here

func(myname) # calling the function

传递了myname指向的实际对象,而不是名称myname本身。在函数内部,另一个名称(x用于引用传递的同一对象。

如果函数内的对象是可变的,则可以修改它,但不能更改外部名称指向的对象。就像你那样

1
anothername = myname

因此,我可以回答您的问题:

它是"传递值",但所有值都只是对对象的引用。


这里的答案是有帮助的,但我发现有必要展现出这种我没有看到的细微差别,我通过随后的cl实验证明了这一点:

  • 不能在函数调用中单独更改不可变对象。(到目前为止,答案已经说了那么多…)
  • 但是,可以在方法调用中重新分配包含在可变对象中的不可变对象。
  • "num"在此处不更改,因为它是一个不可变的数字对象[支持我的第1点]:

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    def incr_num(num):
        num += 1

    num = 0

    num
    0

    incr_num(num)

    num
    0

    "list[0]"这里还有一个不可变的数字对象。

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    def incr_list(list):
        list[0] += 1

    list = [0]

    list[0]
    0

    incr_list(list)

    list[0]
    1

    那么,作为一个不可变的数字对象,"list[0]"是如何改变的(支持我的第2点),而上面例子的数字对象"num"没有改变?不可变数字对象"list[0]"包含在可变列表对象"list"中,而第一个示例中的"num"只是一个非连续数字对象。

    虽然我的想法很好,但我觉得@stephen pape的最佳答案(以下引用)和其他一些类似的答案并不完全正确(这促使我写下这个答案):

    Some objects, like strings, tuples, and numbers, are immutable.
    Altering them inside a function/method will create a new instance and
    the original instance outside the function/method is not changed.

    上面的第二个代码实验显示一个数字对象("list[0]")在一个方法中被更改,然后函数外部的原始实例发生了更改。


    传递了一个引用,但如果参数是不可变的对象,则在方法中修改它将创建一个新实例。


    对象被传递。不是副本,而是对基础对象的引用。


    我还建议查看copy模块:

    用于复制的python文档

    它将帮助您了解底层问题以及如何使用它来执行自己的深度复制。


    参考文献:

    1
    2
    3
    4
    5
    6
    7
    8
    >>> x = [0,1,2,3]
    >>> def foo(x_list):
        x_list[0] = 1


    >>> foo(x)
    >>> x
    [1, 1, 2, 3]


    请让我举个简陋的例子

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    def swap(a, b):
        x = a
        print id(x)
        print id(a)
        print id(b)
        a = b

        print id(a)
        b = x
        print id(b)
        a[0]= '20'




    var1 = ['1','2','3','4']
    var2 = ['5','6','7','8','9']
    print id(var1)
    print id(var2)

    swap(var1, var2)

    print id(var1)
    print id(var2)
    print var1
    print var2

    产生以下结果

    28329344 VAR128331264 VAR228329344 X28329344 A28331264 BA= B之后28331264 AB=x之后28329344 B返回后28329344 VAR128331264 VAR2['1'、'2'、'3'、'4']['20'、'6'、'7'、'8'、'9']

    映射到内存地址28329344 28331264号变1变2A BXA= B之后一B=x之后乙在[0]='20'之后〔0〕="20"返回后['1'、'2'、'3'、'4']['20'、'6'、'7'、'8'、'9']