The difference between writing something on one line and several lines

Where is the difference when I write something on one line divided by , and on two lines. Apparently, I do not understand the difference, because although the two functions below should return the same.

 def fibi(n): a, b = 0, 1 for i in range(n): a, b = b, a + b return a print(fibi(6)) > 8 # expected result (Fibonacci) 

But

 def fibi(n): a, b = 0, 1 for i in range(n): a = b b = a + b return a print(fibi(6)) > 32 
+5
source share
6 answers

This is due to unpacking Python tuples. In the first of these, Python collects the values ​​on the right, makes them a tuple, and then assigns the values ​​of the tuple individually to the names on the left. So if a == 1 and b == 2:

  a, b = b, a + b => a, b = (2, 3) => a = 2, b = 3 

But in the second example, this is a normal assignment:

  a = b => a = 2 b = a + b => b = 4 
+13
source

To find a replacement for

 a, b = b, a + b 

you must be aware that this assignment is performed "step by step".

So its equivalent

 old_a = a a = b b = old_a + b # note the old_a here, as a has been replaced in the meanwhile. 

Demo:

 def fibi(n): a, b = 0, 1 for i in range(n): a, b = b, a + b return a def fibi2(n): a, b = 0, 1 for i in range(n): old_a = a a = b b = old_a + b return a >>> fibi(0) 0 >>> fibi(1) 1 >>> fibi(2) 1 >>> fibi(3) 2 >>> fibi(4) 3 >>> fibi(5) 5 >>> fibi(6) 8 >>> fibi(7) 13 >>> >>> >>> >>> fibi2(0) 0 >>> fibi2(1) 1 >>> fibi2(2) 1 >>> fibi2(3) 2 >>> fibi2(4) 3 >>> fibi2(5) 5 >>> fibi2(6) 8 >>> fibi2(7) 
+2
source

Your difference occurs in the lines:

1)

 >>> a, b = 0, 1 >>> a, b = b, a+b >>> a 1 >>> b 1 

vs

2)

 >>> a, b = 0, 1 >>> a = b >>> b = a+b >>> a 1 >>> b 2 

in the first case, a = 1 and b = 0 + 1 until the values ​​of the variables change. You basically say "with (a,b) in the given state X, set (a,b) to the values (0,1) ."

A good way to see the difference in such things is to use the disassemble module (see the link to see the meaning of the codes):

 >>> from dis import dis >>> a, b = 0, 1 >>> dis('a, b = b, a+b') 1 0 LOAD_NAME 0 (b) 3 LOAD_NAME 1 (a) 6 LOAD_NAME 0 (b) 9 BINARY_ADD 10 ROT_TWO 11 STORE_NAME 1 (a) 14 STORE_NAME 0 (b) 17 LOAD_CONST 0 (None) 20 RETURN_VALUE >>> a, b = 0, 1 >>> dis('a = b; b = a+b') 1 0 LOAD_NAME 0 (b) 3 STORE_NAME 1 (a) 6 LOAD_NAME 1 (a) 9 LOAD_NAME 0 (b) 12 BINARY_ADD 13 STORE_NAME 0 (b) 16 LOAD_CONST 0 (None) 19 RETURN_VALUE 
+1
source

The difference is that in the second example, you set a to b before the link a . Your values ​​in the second example will be disabled. Here is an example:

 a = 5 b = 6 

Ex.1:

 a, b = b, a+b // a = 6 and b = 11 

ex.2:

 a = b // a = 6 b = a + b // b = 6+6 or 12 

The first example is correct

0
source

In the first case, the teams

 a, b = b, a + b; 

will do the sum a + b , and then complete the task. In this case, b always contains 1. This explains why the final result is 6, since you add 1 six times.

The second code you posted is correct.

0
source

The perfect explanation from Raymond Hettinger can be found in this PyCon 2013 video between 33:13 and 38:17:

https://www.youtube.com/watch?v=OSGv2VnC0go

Quote from his presentation:

  • Do not underestimate the benefits of updating state variables at the same time.
  • eliminates a whole class of errors due to out-of-line updates
0
source

Source: https://habr.com/ru/post/1237345/


All Articles