我在尝试学习python时遇到了这个问题。考虑以下功能:
def swap0(s1, s2):
assert type(s1) == list and type(s2) == list
tmp = s1[:]
s1 = s2[:]
s2 = tmp
return
s1 = [1]
s2 = [2]
swap0(s1, s2)
print s1, s2
s1和s2会打印什么?
运行问题后,我发现print语句将打印1 2.似乎s1和s2的值没有从swap0
函数改变。我能想到的唯一解释是因为这条线。
tmp = s1[:]
由于s1 [:]是一个副本,因此在函数调用中s1的值不会改变是有意义的。但是因为swap0
的参数是(s1,s2),我不确定在执行tmp = s1 [:]之后。我随时
s1 = something...
它将是对s1副本的引用,而不是s1本身。有人可以提供更好的解释吗?感谢。
答案 0 :(得分:23)
这是因为它为s1
函数中的s2
和swap0
分配了新值。这些赋值不会在函数外传播。如果你只是在函数调用的位置复制并粘贴函数体,你会发现它是有效的。
您可以通过修改参数引用的对象而不是参数本身来解决此问题:
def swap0(s1, s2):
assert type(s1) == list and type(s2) == list
tmp = s1[:]
s1[:] = s2
s2[:] = tmp
然而,在Python中进行交换的更简单和更好的方法就是:
s1, s2 = s2, s1
这也只会将这些特定引用交换到列表,而不是列表内容本身。
答案 1 :(得分:11)
实际上,您的最终print
会打印出s1
和s2
的原始值。这是因为您只是在函数范围内交换它们。这样做不会影响它们在函数外部的值(即在调用函数后它们的值之后)
如果它们是可变类型(list
,set
,dict
等),那么您可以在swap
内就地修改它们。但是,这限制了swap
仅适用于可变类型。
因此,您最好以相反的顺序返回输入:
def swap(s1, s2):
return s2, s1
s1 = 'a'
s2 = 'b'
s1, s2 = swap(s1, s2)
print s1, s2 # prints 'b a'
当然,您可以按如下方式在一行中执行此操作:
s1, s2 = s2, s1
干杯!
答案 2 :(得分:6)
其他答案解释了出了什么问题。这是一个做你想要的版本:
def swap(s1, s2):
assert isinstance(s1, list) and isinstance(s2, list)
s1[:], s2[:] = s2[:], s1[:]
另请参阅:isinstance vs. type
答案 3 :(得分:4)
在函数内部,您使用右侧的值重新绑定本地变量s1
和s2
(因为您正在使用切片,这些值也是本地的制作副本)。即使您更改了这些局部变量的内容,也不会更改调用范围中列表的内容,因为它们不再引用相同的列表。
答案 4 :(得分:2)
这是一个完成目标的单行功能:
swap = lambda x: (x[1], x[0])
答案 5 :(得分:2)
如果两个列表具有相同的长度,您也可以使用索引和循环通过旧的交换方法执行此操作。这是一种老派,但有助于理解索引
a = [1, 2, 3, 4, 5, 6, 7, 8, 9, 0]
b = [0, 9, 8, 7, 6, 5, 4, 3, 2, 1]
for i in range(0, len(a)):
a[i] = a[i] + b[i]
b[i] = a[i] - b[i]
a[i] = a[i] - b[i]
print(a)
print(b)
这将输出为:
[0,9,8,7,6,5,4,3,2,1]
[1,2,3,4,5,6,7,8,9,0]
或者它也可以使用Xor完成。 Xor运算符是一个按位运算符,例如在操作数之间执行Xor运算。
a = 5 #0b101
b = 4 #0b100
c = a ^ b #0b001
这里0b101
是5的二进制表示,0b100
是4的二进制表示,当你这些时,你将输出为0b001
,即1。如果输入中只有一个输入为1,则返回1输出结果。如果两个输入均为0或两者均为1,则输出结果为0。
我们可以使用Xor交换两个变量,例如:
a = 5 # 0b0101
b = 9 # 0b1001
a = a ^ b # Xor (0b0101, 0b1001) = 0b1100 (12)
b = a ^ b # Xor (0b1100, 0b1001) = 0b0101 (5)
a = a ^ b # Xor (0b1100, 0b0101) = 0b1001 (9)
print("a = {} and b = {}".format(a, b))
输出将为a = 9 and b = 5
类似地,我们也可以通过对项目进行Xor操作来交换两个列表,例如:
a = [ 1, 2, 3, 4, 5, 6, 7, 8, 9, 0 ]
b = [ 0, 9, 8, 7, 6, 5, 4, 3, 2, 1 ]
for i in range(0, len(a)) :
a[i] = a[i] ^ b[i]
b[i] = a[i] ^ b[i]
a[i] = a[i] ^ b[i]
print(a)
print(b)
输出:
[0, 9, 8, 7, 6, 5, 4, 3, 2, 1]
[1, 2, 3, 4, 5, 6, 7, 8, 9, 0]
让我们看另一个场景,如果我们需要交换列表中的项目,例如:
我们有一个像x = [ 13, 3, 7, 5, 11, 1 ]
这样的列表,我们需要交换它的项目x = [ 1, 3, 5, 7 , 11, 13 ]
所以我们可以通过使用两个按位运算符Xor ^
和赞美~
代码:
# List of items
a = [ 13, 3, 7, 5, 11, 1 ]
# Calculated the length of list using len() and
# then calulated the middle index of that list a
half = len(a) // 2
# Loop from 0 to middle index
for i in range(0, half) :
# This is to prevent index 1 and index 4 values to get swap
# because they are in their right place.
if (i+1) % 2 is not 0 :
#Here ~i means the compliment of i and ^ is Xor,
# if i = 0 then ~i will be -1
# As we know -ve values index the list from right to left
# so a [-1] = 1
a[i] = a[i] ^ a[~i]
a[~i] = a[i] ^ a[~i]
a[i] = a[i] ^ a[~i]
print(a)
因此输出将为[1, 3, 5, 7, 11, 13]
答案 6 :(得分:1)
哟可以有这个:
def swap(x , y):
x , y = y , x
return x , y
x = 5
y = 10
print ('x is {0} and y is {1}'.format(x,y)) # x is 5 and y is 10
x , y = swap(x,y) # doing swap
print ('x is {0} and y is {1}'.format(x,y)) # x is 10 and y is 5
答案 7 :(得分:-1)
根本不需要功能。 a,b = b,a可以解决问题。
>>> a,b=1,2
>>> print (a,b)
(1, 2)
>>> a,b=b,a
>>> print (a,b)
(2, 1)
>>>
它也适用于数组。 但是,如果您想要这里的功能,那就是
def swap(a,b)
return b,a