7

Can someone please explain to me what line 4 is doing?

1 def fib2(n):  # return Fibonacci series up to n
2 ...     """Return a list containing the Fibonacci series up to n."""
3...     result = []
4...     a, b = 0, 1  #this line
5...     while a < n:
6...         result.append(a)
7...         a, b = b, a+b
8...     return result    
vaultah
  • 44,105
  • 12
  • 114
  • 143
Jackle
  • 81
  • 1
  • 1
  • 2

2 Answers2

16

What you describe is tuple assignment:

a, b = 0, 1

is equivalent to a = 0 and b = 1.

It can however have interesting effects if you for instance want to swap values. Like:

a,b = b,a

will first construct a tuple (b,a) and then untuple it and assign it to a and b. This is thus not equivalent to:

#not equal to
a = b
b = a

but to (using a temporary):

t = a
a = b
b = t

In general if you have a comma-separated list of variables left of the assignment operator and an expression that generates a tuple, the tuple is unpacked and stored in the values. So:

t = (1,'a',None)
a,b,c = t

will assign 1 to a, 'a' to b and None to c. Note that this is not syntactical sugar: the compiler does not look whether the number of variables on the left is the same as the length of the tuple on the right, so you can return tuples from functions, etc. and unpack them in separate variables.

Willem Van Onsem
  • 443,496
  • 30
  • 428
  • 555
  • 2
    I've always known it as tuple packing/unpacking, or more generally *sequence unpacking*. See [Tuples and Sequences](https://docs.python.org/2/tutorial/datastructures.html#tuples-and-sequences) – Peter Wood Jan 12 '17 at 14:37
  • Remember functions and class methods can return tuples too. For example: `def myfunc(): return 2,4` can be used as `a, b = myfunc()` which will make `a = 2` and `b = 4` or `myfunc()[0]` which will return `2`. – Andrej Žukov-Gregorič Jan 12 '17 at 15:01
  • 1
    @AndrejŽukov-Gregorič: that's why in the last code fragment I explicitly first constructed a tuple and stored it into `t`: such that one can reason this is no syntactical sugar, but actually tuple unpacking. – Willem Van Onsem Jan 12 '17 at 15:03
  • 1
    Yep +1 :) - just added that comment so that people see tuple returning functions. – Andrej Žukov-Gregorič Jan 12 '17 at 15:05
1

For the purposes of reading, all it's doing is setting a and b, so that a = 0 and b = 1. Similarly, in line 7, it's setting a to b and b to the sum of a and b.

More specifically, it's setting tuples. Tuples are invariant, in that once they're created, their values can't change. Tuples are pervasive in python - you see them almost everywhere.

Typically, you would expect a tuple to be in parenthesis, e.g. (a, b) = (0, 1) would read more cleanly, but they are such a large feature of python that the parenthesis are optional (unless you're constructing a tuple as an argument to a function, and then you need the extra parenthesis to differentiate between a single tuple and multiple arguments. I.e. you would have to say foo((a, b)) to pass a tuple to foo, as foo(a, b) would pass two arguments to it.)

Tuples can be any length. You can write a, b, c, d, e = 0, 1, 2, 3, 4, or you can have a function return a tuple, e.g.: ret1, ret2, ret3 = foobar(1)

Scott Mermelstein
  • 15,174
  • 4
  • 48
  • 76