What is the most efficient way to toggle between 0 and 1?
Solution using NOT
If the values are boolean, the fastest approach is to use the not operator:
>>> x = True
>>> x = not x # toggle
>>> x
False
>>> x = not x # toggle
>>> x
True
>>> x = not x # toggle
>>> x
False
Solution using subtraction
If the values are numerical, then subtraction from the total is a simple and fast way to toggle values:
>>> A = 5
>>> B = 3
>>> total = A + B
>>> x = A
>>> x = total - x # toggle
>>> x
3
>>> x = total - x # toggle
>>> x
5
>>> x = total - x # toggle
>>> x
3
Solution using XOR
If the value toggles between 0 and 1, you can use a bitwise exclusive-or:
>>> x = 1
>>> x ^= 1
>>> x
0
>>> x ^= 1
>>> x
1
The technique generalizes to any pair of integers. The xor-by-one step is replaced with a xor-by-precomputed-constant:
>>> A = 205
>>> B = -117
>>> t = A ^ B # precomputed toggle constant
>>> x = A
>>> x ^= t # toggle
>>> x
-117
>>> x ^= t # toggle
>>> x
205
>>> x ^= t # toggle
>>> x
-117
(This idea was submitted by Nick Coghlan and later generalized by #zxxc.)
Solution using a dictionary
If the values are hashable, you can use a dictionary:
>>> A = 'xyz'
>>> B = 'pdq'
>>> d = {A:B, B:A}
>>> x = A
>>> x = d[x] # toggle
>>> x
'pdq'
>>> x = d[x] # toggle
>>> x
'xyz'
>>> x = d[x] # toggle
>>> x
'pdq'
Solution using a conditional expression
The slowest way is to use a conditional expression:
>>> A = [1,2,3]
>>> B = [4,5,6]
>>> x = A
>>> x = B if x == A else A
>>> x
[4, 5, 6]
>>> x = B if x == A else A
>>> x
[1, 2, 3]
>>> x = B if x == A else A
>>> x
[4, 5, 6]
Solution using itertools
If you have more than two values, the itertools.cycle() function provides a generic fast way to toggle between successive values:
>>> import itertools
>>> toggle = itertools.cycle(['red', 'green', 'blue']).next
>>> toggle()
'red'
>>> toggle()
'green'
>>> toggle()
'blue'
>>> toggle()
'red'
>>> toggle()
'green'
>>> toggle()
'blue'
Note that in Python 3 the next() method was changed to __next__(), so the first line would be now written as toggle = itertools.cycle(['red', 'green', 'blue']).__next__
I always use:
p^=True
If p is a boolean, this switches between true and false.
Here is another non intuitive way. The beauty is you can cycle over multiple values and not just two [0,1]
For Two values (toggling)
>>> x=[1,0]
>>> toggle=x[toggle]
For Multiple Values (say 4)
>>> x=[1,2,3,0]
>>> toggle=x[toggle]
I didn't expect this solution to be almost the fastest too
>>> stmt1="""
toggle=0
for i in xrange(0,100):
toggle = 1 if toggle == 0 else 0
"""
>>> stmt2="""
x=[1,0]
toggle=0
for i in xrange(0,100):
toggle=x[toggle]
"""
>>> t1=timeit.Timer(stmt=stmt1)
>>> t2=timeit.Timer(stmt=stmt2)
>>> print "%.2f usec/pass" % (1000000 * t1.timeit(number=100000)/100000)
7.07 usec/pass
>>> print "%.2f usec/pass" % (1000000 * t2.timeit(number=100000)/100000)
6.19 usec/pass
stmt3="""
toggle = False
for i in xrange(0,100):
toggle = (not toggle) & 1
"""
>>> t3=timeit.Timer(stmt=stmt3)
>>> print "%.2f usec/pass" % (1000000 * t3.timeit(number=100000)/100000)
9.84 usec/pass
>>> stmt4="""
x=0
for i in xrange(0,100):
x=x-1
"""
>>> t4=timeit.Timer(stmt=stmt4)
>>> print "%.2f usec/pass" % (1000000 * t4.timeit(number=100000)/100000)
6.32 usec/pass
The not operator negates your variable (converting it into a boolean if it isn't already one). You can probably use 1 and 0 interchangeably with True and False, so just negate it:
toggle = not toggle
But if you are using two arbitrary values, use an inline if:
toggle = 'a' if toggle == 'b' else 'b'
Just between 1 and 0, do this
1-x
x can take 1 or 0
Trigonometric approach, just because sin and cos functions are cool.
>>> import math
>>> def generator01():
... n=0
... while True:
... yield abs( int( math.cos( n * 0.5 * math.pi ) ) )
... n+=1
...
>>> g=generator01()
>>> g.next()
1
>>> g.next()
0
>>> g.next()
1
>>> g.next()
0
Surprisingly nobody mention good old division modulo 2:
In : x = (x + 1) % 2 ; x
Out: 1
In : x = (x + 1) % 2 ; x
Out: 0
In : x = (x + 1) % 2 ; x
Out: 1
In : x = (x + 1) % 2 ; x
Out: 0
Note that it is equivalent to x = x - 1, but the advantage of modulo technique is that the size of the group or length of the interval can be bigger then just 2 elements, thus giving you a similar to round-robin interleaving scheme to loop over.
Now just for 2, toggling can be a bit shorter (using bit-wise operator):
x = x ^ 1
one way to toggle is by using Multiple assignment
>>> a = 5
>>> b = 3
>>> t = a, b = b, a
>>> t[0]
3
>>> t = a, b = b, a
>>> t[0]
5
Using itertools:
In [12]: foo = itertools.cycle([1, 2, 3])
In [13]: next(foo)
Out[13]: 1
In [14]: next(foo)
Out[14]: 2
In [15]: next(foo)
Out[15]: 3
In [16]: next(foo)
Out[16]: 1
In [17]: next(foo)
Out[17]: 2
The easiest way to toggle between 1 and 0 is to subtract from 1.
def toggle(value):
return 1 - value
Using exception handler
>>> def toogle(x):
... try:
... return x/x-x/x
... except ZeroDivisionError:
... return 1
...
>>> x=0
>>> x=toogle(x)
>>> x
1
>>> x=toogle(x)
>>> x
0
>>> x=toogle(x)
>>> x
1
>>> x=toogle(x)
>>> x
0
Ok, I'm the worst:
import math
import sys
d={1:0,0:1}
l=[1,0]
def exception_approach(x):
try:
return x/x-x/x
except ZeroDivisionError:
return 1
def cosinus_approach(x):
return abs( int( math.cos( x * 0.5 * math.pi ) ) )
def module_approach(x):
return (x + 1) % 2
def subs_approach(x):
return x - 1
def if_approach(x):
return 0 if x == 1 else 1
def list_approach(x):
global l
return l[x]
def dict_approach(x):
global d
return d[x]
def xor_approach(x):
return x^1
def not_approach(x):
b=bool(x)
p=not b
return int(p)
funcs=[ exception_approach, cosinus_approach, dict_approach, module_approach, subs_approach, if_approach, list_approach, xor_approach, not_approach ]
f=funcs[int(sys.argv[1])]
print "\n\n\n", f.func_name
x=0
for _ in range(0,100000000):
x=f(x)
How about an imaginary toggle that stores not only the current toggle, but a couple other values associated with it?
toggle = complex.conjugate
Store any + or - value on the left, and any unsigned value on the right:
>>> x = 2 - 3j
>>> toggle(x)
(2+3j)
Zero works, too:
>>> y = -2 - 0j
>>> toggle(y)
(-2+0j)
Easily retrieve the current toggle value (True and False represent + and -), LHS (real) value, or RHS (imaginary) value:
>>> import math
>>> curr = lambda i: math.atan2(i.imag, -abs(i.imag)) > 0
>>> lhs = lambda i: i.real
>>> rhs = lambda i: abs(i.imag)
>>> x = toggle(x)
>>> curr(x)
True
>>> lhs(x)
2.0
>>> rhs(x)
3.0
Easily swap LHS and RHS (but note that the sign of the both values must not be important):
>>> swap = lambda i: i/-1j
>>> swap(2+0j)
2j
>>> swap(3+2j)
(2+3j)
Easily swap LHS and RHS and also toggle at the same time:
>>> swaggle = lambda i: i/1j
>>> swaggle(2+0j)
-2j
>>> swaggle(3+2j)
(2-3j)
Guards against errors:
>>> toggle(1)
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
TypeError: descriptor 'conjugate' requires a 'complex' object but received a 'int'
Perform changes to LHS and RHS:
>>> x += 1+2j
>>> x
(3+5j)
...but be careful manipulating the RHS:
>>> z = 1-1j
>>> z += 2j
>>> z
(1+1j) # whoops! toggled it!
Variables a and b can be ANY two values, like 0 and 1, or 117 and 711, or "heads" and "tails". No math is used, just a quick swap of the values each time a toggle is desired.
a = True
b = False
a,b = b,a # a is now False
a,b = b,a # a is now True
I use abs function, very useful on loops
x = 1
for y in range(0, 3):
x = abs(x - 1)
x will be 0.
Let's do some frame hacking. Toggle a variable by name. Note: This may not work with every Python runtime.
Say you have a variable "x"
>>> import inspect
>>> def toggle(var_name):
>>> frame = inspect.currentframe().f_back
>>> vars = frame.f_locals
>>> vars[var_name] = 0 if vars[var_name] == 1 else 1
>>> x = 0
>>> toggle('x')
>>> x
1
>>> toggle('x')
>>> x
0
If you are dealing with an integer variable, you can increment 1 and limit your set to 0 and 1 (mod)
X = 0 # or X = 1
X = (X + 1)%2
Switching between -1 and +1 can be obtained by inline multiplication; used for calculation of pi the 'Leibniz' way (or similar):
sign = 1
result = 0
for i in range(100000):
result += 1 / (2*i + 1) * sign
sign *= -1
print("pi (estimate): ", result*4)
You can make use of the index of lists.
def toggleValues(values, currentValue):
return values[(values.index(currentValue) + 1) % len(values)]
> toggleValues( [0,1] , 1 )
> 0
> toggleValues( ["one","two","three"] , "one" )
> "two"
> toggleValues( ["one","two","three"] , "three")
> "one"
Pros: No additional libraries, self.explanatory code and working with arbitrary data types.
Cons: not duplicate-save.
toggleValues(["one","two","duped", "three", "duped", "four"], "duped")
will always return "three"
Related
>>> fibonacci = [0,1,1,2,3,5,8,13,21,34,55]
>>> odd_numbers = list(filter(lambda x: x % 2, fibonacci))
>>> print(odd_numbers)
[1, 1, 3, 5, 13, 21, 55]
>>> even_numbers = list(filter(lambda x: x % 2 == 0, fibonacci))
>>> print(even_numbers)
[0, 2, 8, 34]
why not like this: lambda x: x % 2 == 1
It is because x % 2 will be read as a boolean and 0 is false and 1 is true (like every number different of 0).
You can try it with
print (True == 1) # True
print (False == 0) # True
Try it online!
In boolean context, non-zero is true (and zero is false). Your version is quite legal as well, it's mostly save some typing.
It is because (x % 2) would return 1 if x is divisible by 2 else 0.Now in Boolean context
1 is for True and 0 is for False.Therefore, in filter function we use only x%2 for getting the odd numbers, because it will give 0(False) if it is divisible by 2 else 1(True).
This behaviour is due to filter function rather than lambda here.
filter definition:
As the name suggests, filter creates a list of elements for which a function returns true.
filter(func, iterable) ---> func is the function which will be executed on iterable.
So now lets see how will filter work in this case.
fibonacci = [0,1,1,2,3,5,8,13,21,34,55]
odd_numbers = list(filter(lambda x: x % 2, fibonacci))
# For each element in fibonacci:
# x = fibonacci[0]
# lambda x: x % 2 will return 0 which is equivalent to False
# Now filter will ignore this as the result of filter is False
# Next Iteration: x = fibonacci[1]
# lambda x: x % 2 will return 1 which is equivalent to True
# So filter will get this value
# therefore, odd_numbers = [1]
# So on and so forth.
Hope it helps.
a = 1
b = 1
id(a) == id(b)
a = 1.0
b = 1.0
id(a) != id(b)
why when a and b is decimal id(a) != id(b) in python ?
when number is decimal python will create two objects ?
The only reason why id(1) == id(1) is that the low integers are cached for performance. Try id(1000) == id(1000)
Actually, sometimes that works. A better test allocates things in different statements:
>>> x = 1
>>> y = 1
>>> id(x) == id(y)
True
>>> x = 1000
>>> y = 1000
>>> id(x) == id(y)
False
>>>
>>> id(1000) == id(1000)
True
The same thing can happen with strings, as well, under even more conditions:
>>> x = 'abcdefg'
>>> y = 'abcdefg'
>>> x is y
True
The bottom line is that using is (or comparing id() values, which is essentially the same thing, but slower) to determine if two objects are identical is only a good strategy under certain circumstances, because Python will cache objects for performance.
One hard and fast rule is that two different mutable objects will have different id values, but as the commenters below point out, there are no guarantees as to whether multiple immutable objects of the same value will or will not be created.
It is easier for the interpreter to cache things when you use literal values. If you make it calculate things, then you can see which things it works really hard to cache, vs. which things it opportunistically caches because it noticed them in proximity:
>>> x = 1000
>>> y = 2000 // 2
>>> x is y
False
>>> x == y
True
>>> x = 1
>>> y = 2 // 2
>>> x is y
True
>>>
>>> x = 'abcdefg'
>>> y = 'abcdefg'
>>> x is y
True
>>> y = 'abc' + 'defg'
>>> x is y
True
>>> x = 'abcdefghijklmnopqrstuvwxyz'
>>> y = 'abcdefghijklmnopqrstuvwxyz'
>>> x is y
True
>>> y = 'abcdefghijklm' + 'nopqrstuvwxyz'
>>> x is y
False
>>> x == y
True
a = 100
x = 1000
def myFun(a,b):
x = b-a
return x
a = myFun(a,x)
x = myFun(a,x)
print(x+a)
I know in first function, a = myFun(a,x) is 900, but why is the result of x = myFun(a,x) ,100?
The name x inside the function myFunc() is independent from the global name x. They live in different namespaces.
As such, when you call myFunc(a, x) the first time, the global x value is unchanged; it remains 1000:
>>> a = 100
>>> x = 1000
>>> def myFun(a,b):
... x = b-a
... return x
...
>>> myFun(a,x)
900
>>> x
1000
If you wanted the global x to change when calling myFunc(), you need to tell Python explicitly that x is to be treated as a global in the function:
def myFun(a,b):
global x
x = b-a
return x
Now assigning to x in the function will set the global name x:
>>> a = 100
>>> x = 1000
>>> def myFun(a,b):
... global x
... x = b-a
... return x
...
>>> myFun(a,x)
900
>>> x
900
What is the difference between the following Python expressions:
# First:
x,y = y,x+y
# Second:
x = y
y = x+y
First gives different results than Second.
e.g.,
First:
>>> x = 1
>>> y = 2
>>> x,y = y,x+y
>>> x
2
>>> y
3
Second:
>>> x = 1
>>> y = 2
>>> x = y
>>> y = x+y
>>> x
2
>>> y
4
y is 3 in First and 4 in Second
In an assignment statement, the right-hand side is always evaluated fully before doing the actual setting of variables. So,
x, y = y, x + y
evaluates y (let's call the result ham), evaluates x + y (call that spam), then sets x to ham and y to spam. I.e., it's like
ham = y
spam = x + y
x = ham
y = spam
By contrast,
x = y
y = x + y
sets x to y, then sets y to x (which == y) plus y, so it's equivalent to
x = y
y = y + y
It is explained in the docs in the section entitled "Evaluation order":
... while evaluating an assignment, the right-hand side is evaluated
before the left-hand side.
The first expression:
Creates a temporary tuple with value y,x+y
Assigned in to another temporary tuple
Extract the tuple to variables x and y
The second statement is actually two expressions, without the tuple usage.
The surprise is, the first expression is actually:
temp=x
x=y
y=temp+y
You can learn more about the usage of comma in "Parenthesized forms".
An observation regarding the left-hand side as well: the order of assignments is guaranteed to be the order of their appearance, in other words:
a, b = c, d
is equivalent functionally to precisely (besides t creation):
t = (c, d)
a = t[0] # done before 'b' assignment
b = t[1] # done after 'a' assignment
This matters in cases like object attribute assignment, e.g.:
class dummy:
def __init__(self): self.x = 0
a = dummy(); a_save = a
a.x, a = 5, dummy()
print(a_save.x, a.x) # prints "5 0" because above is equivalent to "a = dummy(); a_save = a; t = (5, dummy()); a.x = t[0]; a = t[1]"
a = dummy(); a_save = a
a, a.x = dummy(), 5
print(a_save.x, a.x) # prints "0 5" because above is equivalent to "a = dummy(); a_save = a; t = (dummy(), 5); a = t[0]; a.x = t[1]"
This also implies that you can do things like object creation and access using one-liners, e.g.:
class dummy:
def __init__(self): self.x = 0
# Create a = dummy() and assign 5 to a.x
a, a.x = dummy(), 5
I've recently started using Python and this "feature" baffled me. Although there are many answers given, I'll post my understanding anyway.
If I want to swap the values of two variables, in JavaScipt, I'd do the following:
var a = 0;
var b = 1;
var temp = a;
a = b;
b = temp;
I'd need a third variable to temporarily hold one of the values. A very straightforward swap wouldn't work, because both of the variables would end up with the same value.
var a = 0;
var b = 1;
a = b; // b = 1 => a = 1
b = a; // a = 1 => b = 1
Imagine having two different (red and blue) buckets and having two different liquids (water and oil) in them, respectively. Now, try to swap the buckets/liquids (water in blue, and oil in red bucket). You can't do it unless you have an extra bucket.
Python deals with this with a "cleaner" way/solution: Tuple Assignment.
a = 0
b = 1
print(a, b) # 0 1
# temp = a
# a = b
# b = temp
a, b = b, a # values are swapped
print(a, b) # 1 0
I guess, this way Python is creating the "temp" variables automatically and we don't have to worry about them.
In the second case, you assign x+y to x
In the first case, the second result (x+y) is assigned to y
This is why you obtain different results.
After your edit
This happen because, in the statement
x,y = y,x+y
all variables at the right member are evaluated and, then, are stored in the left members. So first proceed with right member, and second with the left member.
In the second statement
x = y
y = x + y
yo first evaluated y and assign it to x; in that way, the sum of x+y is equivalent to a sum of y+y and not of x+x wich is the first case.
The first one is a tuple-like assignment:
x,y = y,x+y
Where x is the first element of the tuple, and y is the second element, thus what you are doing is:
x = y
y = x+y
Wheras the second is doing a straight assign:
x=y
x=x+y
Other answers have already explained how it works, but I want to add a really concrete example.
x = 1
y = 2
x, y = y, x+y
In the last line, first the names are dereferenced like this:
x, y = 2, 1+2
Then the expression is evaluated:
x, y = 2, 3
Then the tuples are expanded and then the assignment happens, equivalent to:
x = 2; y = 3
For newbies, I came across this example that can help explain this:
# Fibonacci series:
# the sum of two elements defines the next
a, b = 0, 1
while a < 10:
print(a)
a, b = b, a+b
With the multiple assignment, set initial values as a=0, b=1.
In the while loop, both elements are assigned new values (hence called 'multiple' assignment). View it as (a,b) = (b,a+b). So a = b, b = a+b at each iteration of the loop. This continues while a<10.
RESULTS:
0
1
1
2
3
5
8
Let's grok the difference.
x, y = y, x + y
It's x tuple xssignment, mexns (x, y) = (y, x + y), just like (x, y) = (y, x)
Stxrt from x quick example:
x, y = 0, 1
#equivxlent to
(x, y) = (0, 1)
#implement xs
x = 0
y = 1
When comes to (x, y) = (y, x + y)
ExFP, have x try directly
x, y = 0, 1
x = y #x=y=1
y = x + y #y=1+1
#output
In [87]: x
Out[87]: 1
In [88]: y
Out[88]: 2
However,
In [93]: x, y = y, x+y
In [94]: x
Out[94]: 3
In [95]: y
Out[95]: 5
The result is different from the first try.
Thx's because Python firstly evaluates the right-hand x+y
So it equivxlent to:
old_x = x
old_y = y
c = old_x + old_y
x = old_y
y = c
In summary, x, y = y, x+y means,
x exchanges to get old_value of y,
y exchanges to get the sum of old value x and old value y,
a, b = 0, 1
while b < 10:
print(b)
a, b = b, a+b
Output
1
1
2
3
5
8
the variables a and b simultaneously get the new values 0 and 1, the same a, b = b, a+b, a and b are assigned simultaneously.
What is the difference between the following Python expressions:
# First:
x,y = y,x+y
# Second:
x = y
y = x+y
First gives different results than Second.
e.g.,
First:
>>> x = 1
>>> y = 2
>>> x,y = y,x+y
>>> x
2
>>> y
3
Second:
>>> x = 1
>>> y = 2
>>> x = y
>>> y = x+y
>>> x
2
>>> y
4
y is 3 in First and 4 in Second
In an assignment statement, the right-hand side is always evaluated fully before doing the actual setting of variables. So,
x, y = y, x + y
evaluates y (let's call the result ham), evaluates x + y (call that spam), then sets x to ham and y to spam. I.e., it's like
ham = y
spam = x + y
x = ham
y = spam
By contrast,
x = y
y = x + y
sets x to y, then sets y to x (which == y) plus y, so it's equivalent to
x = y
y = y + y
It is explained in the docs in the section entitled "Evaluation order":
... while evaluating an assignment, the right-hand side is evaluated
before the left-hand side.
The first expression:
Creates a temporary tuple with value y,x+y
Assigned in to another temporary tuple
Extract the tuple to variables x and y
The second statement is actually two expressions, without the tuple usage.
The surprise is, the first expression is actually:
temp=x
x=y
y=temp+y
You can learn more about the usage of comma in "Parenthesized forms".
An observation regarding the left-hand side as well: the order of assignments is guaranteed to be the order of their appearance, in other words:
a, b = c, d
is equivalent functionally to precisely (besides t creation):
t = (c, d)
a = t[0] # done before 'b' assignment
b = t[1] # done after 'a' assignment
This matters in cases like object attribute assignment, e.g.:
class dummy:
def __init__(self): self.x = 0
a = dummy(); a_save = a
a.x, a = 5, dummy()
print(a_save.x, a.x) # prints "5 0" because above is equivalent to "a = dummy(); a_save = a; t = (5, dummy()); a.x = t[0]; a = t[1]"
a = dummy(); a_save = a
a, a.x = dummy(), 5
print(a_save.x, a.x) # prints "0 5" because above is equivalent to "a = dummy(); a_save = a; t = (dummy(), 5); a = t[0]; a.x = t[1]"
This also implies that you can do things like object creation and access using one-liners, e.g.:
class dummy:
def __init__(self): self.x = 0
# Create a = dummy() and assign 5 to a.x
a, a.x = dummy(), 5
I've recently started using Python and this "feature" baffled me. Although there are many answers given, I'll post my understanding anyway.
If I want to swap the values of two variables, in JavaScipt, I'd do the following:
var a = 0;
var b = 1;
var temp = a;
a = b;
b = temp;
I'd need a third variable to temporarily hold one of the values. A very straightforward swap wouldn't work, because both of the variables would end up with the same value.
var a = 0;
var b = 1;
a = b; // b = 1 => a = 1
b = a; // a = 1 => b = 1
Imagine having two different (red and blue) buckets and having two different liquids (water and oil) in them, respectively. Now, try to swap the buckets/liquids (water in blue, and oil in red bucket). You can't do it unless you have an extra bucket.
Python deals with this with a "cleaner" way/solution: Tuple Assignment.
a = 0
b = 1
print(a, b) # 0 1
# temp = a
# a = b
# b = temp
a, b = b, a # values are swapped
print(a, b) # 1 0
I guess, this way Python is creating the "temp" variables automatically and we don't have to worry about them.
In the second case, you assign x+y to x
In the first case, the second result (x+y) is assigned to y
This is why you obtain different results.
After your edit
This happen because, in the statement
x,y = y,x+y
all variables at the right member are evaluated and, then, are stored in the left members. So first proceed with right member, and second with the left member.
In the second statement
x = y
y = x + y
yo first evaluated y and assign it to x; in that way, the sum of x+y is equivalent to a sum of y+y and not of x+x wich is the first case.
The first one is a tuple-like assignment:
x,y = y,x+y
Where x is the first element of the tuple, and y is the second element, thus what you are doing is:
x = y
y = x+y
Wheras the second is doing a straight assign:
x=y
x=x+y
Other answers have already explained how it works, but I want to add a really concrete example.
x = 1
y = 2
x, y = y, x+y
In the last line, first the names are dereferenced like this:
x, y = 2, 1+2
Then the expression is evaluated:
x, y = 2, 3
Then the tuples are expanded and then the assignment happens, equivalent to:
x = 2; y = 3
For newbies, I came across this example that can help explain this:
# Fibonacci series:
# the sum of two elements defines the next
a, b = 0, 1
while a < 10:
print(a)
a, b = b, a+b
With the multiple assignment, set initial values as a=0, b=1.
In the while loop, both elements are assigned new values (hence called 'multiple' assignment). View it as (a,b) = (b,a+b). So a = b, b = a+b at each iteration of the loop. This continues while a<10.
RESULTS:
0
1
1
2
3
5
8
Let's grok the difference.
x, y = y, x + y
It's x tuple xssignment, mexns (x, y) = (y, x + y), just like (x, y) = (y, x)
Stxrt from x quick example:
x, y = 0, 1
#equivxlent to
(x, y) = (0, 1)
#implement xs
x = 0
y = 1
When comes to (x, y) = (y, x + y)
ExFP, have x try directly
x, y = 0, 1
x = y #x=y=1
y = x + y #y=1+1
#output
In [87]: x
Out[87]: 1
In [88]: y
Out[88]: 2
However,
In [93]: x, y = y, x+y
In [94]: x
Out[94]: 3
In [95]: y
Out[95]: 5
The result is different from the first try.
Thx's because Python firstly evaluates the right-hand x+y
So it equivxlent to:
old_x = x
old_y = y
c = old_x + old_y
x = old_y
y = c
In summary, x, y = y, x+y means,
x exchanges to get old_value of y,
y exchanges to get the sum of old value x and old value y,
a, b = 0, 1
while b < 10:
print(b)
a, b = b, a+b
Output
1
1
2
3
5
8
the variables a and b simultaneously get the new values 0 and 1, the same a, b = b, a+b, a and b are assigned simultaneously.