This question already has answers here:
Multiple assignment and evaluation order in Python
(11 answers)
Closed 7 years ago.
Help me understand difference between list assignment.
I have found that assignment like this
a[0] = b[0]
b[0] = a[0]
Is different from
a[0], b[0] = b[0], a[0]
The values of a and b in both the cases are different , however both of these assignment methods does the same , swapping.
You can run my sample code to see this
a = [0,1,2]
b = [3,4,5]
print "Value of a and b before swaping :"
print "value of a :" , a
print "value of b :" , b
print "\nswap in two line"
a[0] = b[0]
b[0] = a[0]
print "value of a :" , a
print "value of b :" , b
print "\nswap in one line"
# Reinitilizing value of a and b before performing swaping
a = [0,1,2]
b = [3,4,5]
a[0], b[0] = b[0], a[0]
print "value of a :" , a
print "value of b :" , b
How are two methods of assignment different? At the first glance they look the same and do the same thing.
however both of these assignment methods does the same [thing], swapping.
Not quite... The former example doesn't swap. Instead, it takes the first element of b and puts it in the first element of a. Then it takes the first element of a (which used to be the first element in b) and puts it back into b -- leaving a[0] and b[0] with the same value.
When it's all on the same line, python actually does something a little magical. It effectively creates a new tuple (b[0], a[0]) and then uses that tuple to assign things back into b and a. In other words, it behaves effectively the same as:
temp = (b[0], a[0])
a[0] = temp[0]
b[0] = temp[1]
notice how this is logically different from the first case you had.
The difference is the order in which assignment takes place. It has nothing to do with lists however.
The code
a = b
b = a
First assigns b to a, then assigns a to b resulting in both having the value that b had before.
On the other side
a, b = b, a
first evaluates b, a. And then take those values and assign to a and b. This results in a proper swap.
Related
When I was watching videos about introduction to lists for Python I encountered this code:
b = ["banana", "apple", "Microsoft"]
print(b)
(when i print this)
'banana','apple','Microsoft'
I was told to swap the first element and the third element using their index. The working solution that they gave me was this:
b[0], b[2] = b[2], b[0]
print(b)
(when i print this):
'Microsoft','apple','banana'
which was correct. However, I don't understand how the code works, so can anyone please explain?
In most other languages, you would need to create a temporary variable and then switch them over. In Python, this would look like:
a = 1
b = 2
temp = a
a = b
b = temp
Python allows you to swap these in one line.
a = 1
b = 2
a, b = b, a
Now, b = 1 and a = 2
The [brackets] at the end of the variable references the position within the list.
I am a newbie in Python and I'm trying to learn Python through self-learning. I was trying to build Fibonacci series using a while loop. Here is my code, which doesn't return the desired result. Could anyone explain the problem?
a = 0
b = 1
while b<100:
print(b)
a = b
b = a + b
If we define a, b simultaneously like a, b = b, a+b, this works perfectly. Why is this happening? I don't understand because in both cases I am defining a and b the same way.
This is because programming languages like Python, and many others, execute the statements you write in the order you write them.
This means that by the time you execute b = a + b, the value of a has already changed in the previous line.
An easy way to solve this would be using a third variable to store the results temporarily.
a = 0
b = 1
c = 1
while c < 100:
print(c)
c = a + b
a = b
b = c
You are making one small mistake.
When you do a = b, you are changing the value of a. After this, when you do b=a+b, it is actually equivalent to b = b+b => b=2b.
To avoid this, use a temporary variable temp and storethe value of a in it. Then change the value of a using a = b. Then do, a = a+b.
Following is the code:
a=0
b=1
while b<100:
print(b)
temp = a
a = b
b = temp+b
When you do a, b = b, a+b, the previous value of a is used for calculating the new b, we have don a similar thing above by storing the previous value of a in temp
Operator "comma" (,) in Python is used to create a tuple, and it is allowed to omit the parentheses that surround a tuple. The expression a, b = b, a+b is actually an assignment of one tuple to another:
(a, b) = (b, a + b)
This statement is executed by evaluating the tuple constructor on the right-hand side (b, a + b). At this point, a new anonymous tuple (let's call it c) is created and the original values of a and b are not needed anymore. The tuple is then assigned elementwise to the tuple on the left-hand side. The new value of a becomes c[0] (that is, former b) and the new value of b becomes c[1] (that is, former a+b).
Your code is not working because you are changing the value of a before evaluating b. In the Fibonacci series, you want the previous value of a and b. You can use list as above or can introduce another variable to store values.
while True:
temp = a + b
if temp >100:
break
print(temp)
a = b
b = temp
For reference, here is a simple implementation using list:
lst = [0, 1]
while True:
temp = lst[-1]+lst[-2]
if temp>100:
break
lst.append(temp)
print(lst)
This question already has answers here:
Python variable assignment question
(6 answers)
Closed 6 years ago.
I am learning python and I have some question:
What is the difference between
a,b = 0,1
for x in range(100):
print(a)
a=b
b=a+b
and
a,b = 0,1
for x in range(100):
print(a)
a,b = b, a+b
First one gives bad result, but why?
Because you first set a = b, your new b will have the value of twice the old b. You overwrite a to early. A correct implementation should use a temporary variable t:
a,b = 0,1
for x in range(100):
print(a)
t=a
a=b
b=t+b
This is basically what you do by using sequence assignment.
In your original code you have:
a,b = 0,1
for x in range(100):
print(a)
a=b # a now is the old b
b=a+b # b is now twice the old a so b'=2*b instead of b'=a+b
So this would result in jumping by multiplying with two each time (after first loading in 1 into a the first step).
An equivalent problem is the swap of variables. If you want a to take the value of b and vice versa, you cannot write:
#wrong swap
a = b
b = a
Because you lose the value of a after the first assignment. You can use a temporary t:
t = a
a = b
b = t
or use sequence assignment in Python:
a,b = b,a
where a tuple t = (b,a) is first created, and then assigned to a,b.
This question already has answers here:
What is the difference between shallow copy, deepcopy and normal assignment operation?
(12 answers)
Closed 7 years ago.
a = [ 1, 2, [3,4] ]
b = list(a) # create a shallow copy of a
c = a
print (b is a) # False
print (c is a)
b.append(100) # append element to b
print (b)
print (a) # a is unchanged
print (c)
c.append(100) # append element to c
print (b) # b is unchanged
print (a)
print (c)
b[2][0] = -100 # modify an element inside b
print (b)
print (a) # a is changed
print (c)
c[2][0] = -200
print (b) # b is changed
print (a) # a is changed
print (c)
As a beginner in python, I'm not sure what is the meaning of shadow copy, why b.append cannot change a, why c.append cannot change b, why b[2][0] can change a, and why c[2][0] can change b. Thank you!
This is happening because shallow copy b contains references to the list [3,4].
So when you do b[2][0] = -100 then since b is having the reference of the nested list hence both a and b gets affected. If you had done deep copy the list [3,4] would be created again in memory and it will be pointed by b
Due to above reason c[2][0] also changes b since c is also pointing to the same list as a
This question already has answers here:
How to re-assign items in a list in Python?
(4 answers)
Closed 9 years ago.
If I have the following list:
a = [1, 2, 3]
And I run the following code:
for x in a:
x += 1
It seems that this does not change the list a.
However, if I do the following:
for i in range(0, len(a)):
a[i] += 1
This will modify the content of 'a'.
So I guess x and a[i] are referring to elements of a in a different way. What exactly is causing the difference? How are they each referring to elements of a?
When you iterate over a list, each element is yielded, in turn. However, there are different kinds of objects. mutable and immutable. When you do something like:
a += 1
with an immutable object, it translates roughly to:
a = a + 1
Now in this case, you take the object reference by a, add 1 to it to create a new object. Then you assign that new object the name a. Notice how if we do this while iterating, we don't touch the list at all -- We only keep creating new objects and assigning them to the name a.
This is different for a mutable object. Then a += 1 actually changes the object in place. So, the list will see the change because the object that it is holding has changed (mutated). (With the immutable object the object contained in the list wasn't changed because it couldn't be). See this question for more info.
This also makes it a little more clear what's happening when you're iterating by indices. you construct a new integer and you put it in the list (forgetting whatever was in that slot before).
When you say,
for x in [1,2,3]:
x+=1
You are saying, temporarily save x as a variable, and add one to that temporary save. When you get to the next iteration, the garbage man destroys that variable because it was temporary. x is not the spot in the list. It is the value of that spot in the list.
Edit: when I say that it gets deleted, I was not being clear with my words. What happens is that each time through the loop, x is replaced with another value, and so what happened before goes away (unless you did something else with it). With the operations you are using, though, you are not changing the values of any elements in the list. My bad for the confusion.
When you do it the other way,
for x in range(len(lst)):
lst[x] += 1
Then you are talking about the list's values. x is the index of the variable, and can therefore alter the value of the list's value at that spot.
The concept that matters here is the idea of referencing. In Python, variables are references to objects that sit somewhere in memory. Let's use the an arrow → to indicate a reference. Variable → Object. Variable on the left, object on the right.
The array can be visualized as three variables that reference three integer objects.
a[0] → int(1)
a[1] → int(2)
a[2] → int(3)
Now, integer objects are immutable. They can't be changed. When you change an integer variable you're not changing the object the variable refers to. You can't, because ints are immutable. What you can do is make the variable reference a different object.
Direct update
Let's look at the second loop first since it's simpler. What happens if you update the array directly?
for i in range(0, len(a)):
a[i] += 1
First let's unroll the loop:
a[0] += 1
a[1] += 1
a[2] += 1
For integers, a[0] += 1 is equivalent to a[0] = a[0] + 1. First, Python evaluates a[0] + 1 and gets the result int(2). Then it changes a[0] to reference int(2). The second and third statements are evaluated similarly.
a = [1, 2, 3] # a[0] → int(1)
# a[1] → int(2)
# a[2] → int(3)
a[0] += 1 # a[0] → int(2)
a[1] += 1 # a[1] → int(3)
a[2] += 1 # a[2] → int(4)
Indirect update
And what about what I'll call "indirect" updating?
for x in a:
x += 1
Unrolling the loop yields this equivalent series of statements:
x = a[0]
x += 1
x = a[1]
x += 1
x = a[2]
x += 1
What happens at each step, and why isn't the array changed?
x = a[0]
This makes x reference whatever object a[0] references. Both a[0] and x reference the same int(1) object, but x isn't directly connected to a[0]. It refers to whatever a[0] refers to, not to a[0] itself.
x += 1
This changes what x refers to. It has no effect on a[0].
The same thing happens for the second and third assignments. The result is that x is continually changed while the elements of a are merely read from but never modified. And so when the loop terminates a is unchanged.
a = [1, 2, 3] # a[0] → int(1)
# a[1] → int(2)
# a[2] → int(3)
x = a[0] # x → int(1)
x += 1 # x → int(2)
x = a[1] # x → int(2)
x += 1 # x → int(3)
x = a[2] # x → int(3)
x += 1 # x → int(4)
Think of it as in your first loop, x is just a substitute for every element in a. It's not the actual element in a (although by id() it is because they both reference the same object). When you're doing x += 1, you're just changing the value of x and not the value in the list.
In your second for-loop, you're actually modifying the list by doing a[i] += 1.