为什么变量L在sorting(L)
函数调用中被操纵?在其他语言中,L的副本将作为副本传递给sorting()
,以便x
的任何更改都不会更改原始变量?
def sorting(x):
A = x #Passed by reference?
A.sort()
def testScope():
L = [5,4,3,2,1]
sorting(L) #Passed by reference?
return L
>>> print testScope()
>>> [1, 2, 3, 4, 5]
答案 0 :(得分:15)
长话短说:Python使用pass-by-value,但是通过值传递的东西是引用。实际对象有0到无穷大引用指向它们,并且为了改变该对象,无论你是谁以及如何获得对象的引用都无关紧要。
逐步完成您的示例:
L = [...]
在内存中的某处创建一个list
对象,局部变量L
存储对该对象的引用。sorting
(严格地说,可调用对象指向全局名称sorting
)使用L
存储的引用副本进行调用,并将其存储在本地调用的本地x
。sort
中包含的引用所指向的对象的方法x
。它也获得对象的引用(在self
参数中)。它以某种方式改变了该对象(对象,而不是对对象的一些引用,它只是一个内存地址)。testScope
然后返回对该列表对象的另一个引用。print
使用它来请求字符串表示(调用__str__
方法)并输出它。因为它仍然是同一个对象,当然它正在打印排序列表。因此,无论何时将对象传递到任何地方,都可以与任何人共享。函数可以(但通常不会)改变它们被传递的对象(由引用指向),从调用变异方法到赋值成员。请注意,分配成员与分配普通ol'名称不同 - 这仅仅意味着改变本地范围,而不是任何调用者的对象。所以你不能改变调用者的本地人(这就是为什么它不是传递参考)。
进一步阅读:A discussion on effbot.org为什么它不是通过引用传递而不是大多数人所谓的传值。
答案 1 :(得分:9)
Python具有Mutable和Immutable objects的概念。像字符串或整数这样的对象是不可变的 - 您所做的每个更改都会创建一个新的字符串或整数。
列表是可变的,可以在适当的位置进行操作。见下文。
a = [1, 2, 3]
b = [1, 2, 3]
c = a
print a is b, a is c
# False True
print a, b, c
# [1, 2, 3] [1, 2, 3] [1, 2, 3]
a.reverse()
print a, b, c
# [3, 2, 1] [1, 2, 3] [3, 2, 1]
print a is b, a is c
# False True
注意c是如何反转的,因为c“是”a。有许多方法可以将列表复制到内存中的新对象。一种简单的方法是切片:c = a[:]
答案 2 :(得分:1)
在文档中特别提到.sort()
函数会改变集合。如果要迭代已排序的集合,请使用sorted(L)
。这提供了一个生成器,而不仅仅是对列表进行排序。
答案 3 :(得分:0)
a = 1
b = a
a = 2
print b
引用与单独的对象不同。
.sort()
也会改变集合。