【问题标题】:Python: Pass by reference modifies the argument [duplicate]Python:通过引用传递修改参数[重复]
【发布时间】:2015-02-18 13:39:33
【问题描述】:

我在 Python 中有这段代码:

def sortList(x):
   x.sort()
   print "Values inside the function: ", x
   return

mylist = [100,20,30];
sortList(mylist);
print "Values outside the function: ", mylist

输出是:

Values inside the function:  [20, 30, 100]
Values outside the function:  [20, 30, 100]

现在,如果我写x=[1,2,3],而不是写x.sort(),那么输出是:

Values inside the function:  [1, 2, 3]
Values outside the function:  [100, 20, 20]

那么为什么数组“mylist”的值会从函数内部发生变化?也只有当我对其执行一些操作时,而不是当我为它分配全新的值时?

谢谢!

【问题讨论】:

  • 值得一看的是相关的:stackoverflow.com/questions/12797749/…
  • 因为list.sort就地,所以修改对象并返回None,而x = [1, 2, 3]将名称x分配给一个全新的对象,完全不影响mylist

标签: python pass-by-reference


【解决方案1】:

因为参数是通过赋值传递的,所以参数名称 在函数中可以与调用范围内的变量共享对象。因此,对函数中可变参数的就地更改会影响调用者。

并且在您的代码中第一次因为您使用sort() 函数并且它就地更改了x,它会影响调用者并全局更改x!但是当您将新对象分配给x实际上,您在函数内部创建了一个局部变量来引用您的新对象 ([1, 2, 3])。

因此,为了避免可变参数更改,您可以将变量的副本传递给函数:

mylist = [100,20,30];
sortList(mylist[:]);
print "Values outside the function: ", mylist

结果:

Values inside the function:  [20, 30, 100]
Values outside the function:  [100, 20, 30]

作为另一种方式,您可以将参数转换为不可变对象,对其进行更改会引发错误,在这种情况下,您可以将列表转换为元组:

mylist = [100,20,30];
sortList(tuple(mylist));
print "Values outside the function: ", mylist

Traceback (most recent call last):
  File "/home/bluebird/Desktop/try.py", line 7, in <module>
    sortList(tuple(mylist));
  File "/home/bluebird/Desktop/try.py", line 2, in sortList
    x.sort()
AttributeError: 'tuple' object has no attribute 'sort'

【讨论】:

  • 请您多注意一下您的写作吗?就目前而言,这没有意义。另外,除了!之外,还有个标点符号。
  • @jonrsharpe 是的..已修复!
  • @jonrsharpe 欢迎,谢谢!用于提醒;)
【解决方案2】:

您将一个对象值传递给您的函数,然后您正在修改该对象。这会改变对象。只有一个对象,当您将对象传递给函数时,Python 不会创建该对象的独立副本。

现在,如果您将一个完全不同的对象分配给 变量 x,则不会对之前在 x 中的对象执行任何操作。它只是破坏了从x 对该对象的引用。由于该对象仍被mylist 引用,它继续存在就好了。

【讨论】:

  • 我理解您在第一段中所说的话。但是,当您分配时,不应该应用相同的逻辑吗?我的意思是,即使是“分配”也是一种“修改对象”,对吗?如果我在某个地方出错了,请告诉我..
  • 变量是算法中的“占位符”。他们持有价值观。变量 is 不是值。 = 将值放入变量中,它不会修改之前可能存在的值。
【解决方案3】:

这很简单:python 不是通过值(即副本)传递参数,而是通过引用传递参数。因此,在 sortList 中,您可以操作传入的同一个列表。这取决于开发人员的判断力来解决这个问题。一种方法是改用sorted 调用,它为您提供序列的排序副本。其他涉及使用copy.copycopy.deepcopy

【讨论】:

    猜你喜欢
    • 2017-03-21
    • 2017-08-12
    • 2014-03-08
    • 1970-01-01
    • 2015-10-09
    • 2014-03-17
    • 2013-05-16
    • 1970-01-01
    • 2010-09-23
    相关资源
    最近更新 更多