Python simple replace function

I ran into this problem when trying to learn python. Consider the following function:

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 

What will s1 and s2 print?

After completing the problem, I found that the print statement would print 1 2. It seems that the values ​​of s1 and s2 have not changed from the swap0 function. The only explanation I could think of was because of the line.

 tmp = s1[:] 

Since s1 [:] is a copy, it makes sense that the value of s1 will not change in the function call. However, since the swap0 parameter is equal to (s1, s2), I am not sure if after executing tmp = s1 [:]. Every time i do

 s1 = something... 

it will be a link to a copy of s1, not s1. Can anyone suggest a better explanation? Thanks.

+11
python swap
source share
8 answers

This is because it assigns new values s1 and s2 inside the swap0 function. These assignments do not apply outside the function. You will see that it works if you simply copy and paste the body of the function instead of calling the function.

You can get around this by changing the objects referenced by the arguments, rather than the arguments themselves:

 def swap0(s1, s2): assert type(s1) == list and type(s2) == list tmp = s1[:] s1[:] = s2 s2[:] = tmp 

However, it's easier and better to make sharing in Python simple:

 s1, s2 = s2, s1 

This will also replace these specific list links, but not the list contents themselves.

+23
source share

Be that as it may, your final print print the original values s1 and s2 . This is because you only change them as part of the function. This will not affect their values ​​outside the function (i.e., after their values ​​after calling the function)

If they are mutable types ( list , set , dict , etc.), you can change them in place inside swap . However, this limits swap to work only with mutable types.

Therefore, you better return the inputs in the reverse order:

 def swap(s1, s2): return s2, s1 s1 = 'a' s2 = 'b' s1, s2 = swap(s1, s2) print s1, s2 # prints 'ba' 

Of course, you can do it all in one line as follows:

 s1, s2 = s2, s1 

Hooray!

+11
source share

Other answers explain what is going wrong. Here is the version that does what you want:

 def swap(s1, s2): assert isinstance(s1, list) and isinstance(s2, list) s1[:], s2[:] = s2[:], s1[:] 

See also: isinstance vs. type

+6
source share

Inside the function, you bind the local variables s1 and s2 to the values ​​on the right side (which are also local, since you use slices for copying). Even if you change the contents of these local variables, you will not change the contents of the lists in the call area because they no longer belong to the same lists.

+4
source share

Here is a one-line function that performs your task:

 swap = lambda x: (x[1], x[0]) 
+2
source share

You can also do this with the old swaping method, using indexing and looping if both lists are the same length. It's kind of an old school, but it helps to understand indexing.

 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) 

This will give a result like:

  [0,9,8,7,6,5,4,3,2,1] [1,2,3,4,5,6,7,8,9,0] 

Or it can also be done with Xor. The Xor operator is a bitwise operator that performs the Xor operation between operands, for example.

 a = 5 #0b101 b = 4 #0b100 c = a ^ b #0b001 

Here 0b101 is the binary representation of 5, and 0b100 is the binary representation of 4, and when you are XOR, you will be 0b001 ie 1. Xor returns 1 output if one and only one of the inputs is 1. If both inputs are 0 or both have result 1, 0. We can change two variables using Xor, for example:

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

The output will be a = 9 and b = 5

Similarly, we can also swap two lists by doing an Xor operation there, for example:

 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) 

Output:

 [0, 9, 8, 7, 6, 5, 4, 3, 2, 1] [1, 2, 3, 4, 5, 6, 7, 8, 9, 0] 

Let's take another scenario. What if we need to change the elements in the list, for example: we have a list like this x = [ 13, 3, 7, 5, 11, 1 ] , and we need to change it this way x = [ 1, 3, 5, 7 , 11, 13 ] . So we can do this using two bitwise operators Xor ^ and Compliments ~

The code:

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

Thus, the conclusion will be [1, 3, 5, 7, 11, 13]

+2
source share

you can have this:

 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 
+1
source share

There is no need for a function at all. a, b = b, a does its job.

  >>> a,b=1,2 >>> print (a,b) (1, 2) >>> a,b=b,a >>> print (a,b) (2, 1) >>> 

This also works for arrays. But if you want so, the function is here

  def swap(a,b) return b,a 
0
source share

All Articles