Why (a, b = b, a + b) and (a = b, b = a+b) are different in Python

Take Fibonacci sequence as an example

The so-called Fibonacci sequence (also called "rabbit sequence") refers to a series of numbers: 1, 1, 2, 3, 5, 8, 13, 14,…

In fact, this sequence of numbers conforms to this rule: a n = a n-1 + a n-2

If we define a Fibs-like
code that generates Fibonacci sequence as follows:

>>> class Fibs:
	def __init__(self):
		self.a = 0
		self.b = 1
	def __iter__(self):
		return self
	def __next__(self):
		self.a, self.b = self.b, self.a+self.b
		return self.a

After instantiating the object, print a series of numbers within 20
-be sure to set the range, otherwise it will not stop

>>> fibs = Fibs()
>>> for each in fibs:
	if each < 20:
		print(each, end = ' ')
	else:
		break

	
1 1 2 3 5 8 13 

We noticed that there is a strange assignment statement in the class:

self.a, self.b = self.b, self.a+self.b

If you think this assignment statement is equivalent to:

>>> self.a = self.b
>>> self.b = self.a + self.b

The program becomes:

>>> class Fibs:
	def __init__(self):
		self.a = 0
		self.b = 1
	def __iter__(self):
		return self
	def __next__(self):
		self.a = self.b
		self.b = self.a + self.b
		return self.a

	
>>> fibs = Fibs()
>>> for each in fibs:
	if each < 20:
		print(each, end = ' ')
	else:
		break

	
1 2 4 8 16 

As you can see, the results of the operation are very strange, anyway, it is not a rabbit sequence!

Python's multi-variable assignment

To understand the above assignment operation, you need to understand Python's copy rules:

self.a, self.b = self.b, self.a+self.b

1 Python assignment is to assign the value on the right side to the left side.
2 If there is an operation on the right side of the equal sign, then the operation is performed before the assignment

That is to say:
1 First calculate the operation self.a + self.b = 0+1 = 1
2 on the right side of the equal sign, then assign self.b = 1, and assign it to self.a
3 Then the calculated self.a + self .b = 0+1 = 1, assign value to self.b

How to change it?

Just add an intermediate variable!

>>> class Fibs:
	def __init__(self):
		self.a = 0
		self.b = 1
	def __iter__(self):
		return self
	def __next__(self):
		temp = self.a + self.b
		self.a = self.b
		self.b = temp
		return self.a

	
>>> fibs = Fibs()
>>> for each in fibs:
	if each < 20:
		print(each)
	else:
		break

	
1
1
2
3
5
8
13

Infinite loop is terrible, how to modify the class function so that the calculation can stop?

Look at the code directly:

class Fibs:
	def __init__(self, n = 10):
		self.a = 0
		self.b = 1
		self.n = n
	def __iter__(self):
		return self
	def __next__(self):
		
		self.a, self.b = self.b, self.a + self.b
		if self.a > self.n:
			raise StopIteration
		return self.a

__iter__ is an iterator method, with StopIteration you can stop the iteration.
When instantiating an object, you can also control the depth of iteration by entering the value of n.

Happy! Optimized!

Guess you like

Origin blog.csdn.net/Haoyu_xie/article/details/106229539
B