python a,b = b,a implementation? How is it different from C++ swap function?
Clash Royale CLAN TAG#URR8PPP
up vote
15
down vote
favorite
I met this problem when I want to try a python version of:
https://leetcode.com/problems/first-missing-positive/discuss/17071/My-short-c++-solution-O(1)-space-and-O(n)-time
I am not sure why a[0], a[a[0]] = a[a[0]], a[0]
this one does not do the swap?
>>> nums
[2, 1, 0]
>>> a = [2,1,0]
>>> a[0], a[a[0]] = a[a[0]], a[0]
>>> a
[2, 1, 0]
>>> a[0]
2
>>> a[0],a[2] = a[2], a[0]
>>> a
[0, 1, 2]
My guess is that the implementation of a, b = b, a syntax is something like:
tmp = a[0] (tmp = 2)
a[0] = a[a[0]] (a[0] = a[2] = 0)
a[a[0]] = tmp (a[a[0]] = a[0] = tmp = 2)
Then I checked the implementation of swap function in C++. I know nothing about C++, but it looks like the idea is the same
:
http://www.cplusplus.com/reference/algorithm/swap/
The behavior of these function templates is equivalent to:
template <class T> void swap (T& a, T& b)
T c(std::move(a)); a=std::move(b); b=std::move(c);
template <class T, size_t N> void swap (T (&a)[N], T (&b)[N])
for (size_t i = 0; i<N; ++i) swap (a[i],b[i]);
we have c = a, then a = b and b = a
So why C++ swap function does not have this problem?
And how to write this kind of swap function in a pythonic way?
python algorithm
add a comment |Â
up vote
15
down vote
favorite
I met this problem when I want to try a python version of:
https://leetcode.com/problems/first-missing-positive/discuss/17071/My-short-c++-solution-O(1)-space-and-O(n)-time
I am not sure why a[0], a[a[0]] = a[a[0]], a[0]
this one does not do the swap?
>>> nums
[2, 1, 0]
>>> a = [2,1,0]
>>> a[0], a[a[0]] = a[a[0]], a[0]
>>> a
[2, 1, 0]
>>> a[0]
2
>>> a[0],a[2] = a[2], a[0]
>>> a
[0, 1, 2]
My guess is that the implementation of a, b = b, a syntax is something like:
tmp = a[0] (tmp = 2)
a[0] = a[a[0]] (a[0] = a[2] = 0)
a[a[0]] = tmp (a[a[0]] = a[0] = tmp = 2)
Then I checked the implementation of swap function in C++. I know nothing about C++, but it looks like the idea is the same
:
http://www.cplusplus.com/reference/algorithm/swap/
The behavior of these function templates is equivalent to:
template <class T> void swap (T& a, T& b)
T c(std::move(a)); a=std::move(b); b=std::move(c);
template <class T, size_t N> void swap (T (&a)[N], T (&b)[N])
for (size_t i = 0; i<N; ++i) swap (a[i],b[i]);
we have c = a, then a = b and b = a
So why C++ swap function does not have this problem?
And how to write this kind of swap function in a pythonic way?
python algorithm
1
if you use a different list (likea = [1,2,3,4]
) you will see it does change the values, but the problem is in the order of execution, soa[a[0]]
points to different elements the two times its called.
â Zinki
Aug 21 at 13:54
Possible duplicate of Multiple assignment and evaluation order in Python
â agtoever
Aug 21 at 14:04
Fun fact: if you usea = [2,3,4]
instead, you get "List assignment index out of range".
â molbdnilo
Aug 21 at 14:08
I believe there's a problem somewhat related to the "sequence points" problem in C++, in that your left-hand side both modifies and usesa[0]
.
â molbdnilo
Aug 21 at 14:26
add a comment |Â
up vote
15
down vote
favorite
up vote
15
down vote
favorite
I met this problem when I want to try a python version of:
https://leetcode.com/problems/first-missing-positive/discuss/17071/My-short-c++-solution-O(1)-space-and-O(n)-time
I am not sure why a[0], a[a[0]] = a[a[0]], a[0]
this one does not do the swap?
>>> nums
[2, 1, 0]
>>> a = [2,1,0]
>>> a[0], a[a[0]] = a[a[0]], a[0]
>>> a
[2, 1, 0]
>>> a[0]
2
>>> a[0],a[2] = a[2], a[0]
>>> a
[0, 1, 2]
My guess is that the implementation of a, b = b, a syntax is something like:
tmp = a[0] (tmp = 2)
a[0] = a[a[0]] (a[0] = a[2] = 0)
a[a[0]] = tmp (a[a[0]] = a[0] = tmp = 2)
Then I checked the implementation of swap function in C++. I know nothing about C++, but it looks like the idea is the same
:
http://www.cplusplus.com/reference/algorithm/swap/
The behavior of these function templates is equivalent to:
template <class T> void swap (T& a, T& b)
T c(std::move(a)); a=std::move(b); b=std::move(c);
template <class T, size_t N> void swap (T (&a)[N], T (&b)[N])
for (size_t i = 0; i<N; ++i) swap (a[i],b[i]);
we have c = a, then a = b and b = a
So why C++ swap function does not have this problem?
And how to write this kind of swap function in a pythonic way?
python algorithm
I met this problem when I want to try a python version of:
https://leetcode.com/problems/first-missing-positive/discuss/17071/My-short-c++-solution-O(1)-space-and-O(n)-time
I am not sure why a[0], a[a[0]] = a[a[0]], a[0]
this one does not do the swap?
>>> nums
[2, 1, 0]
>>> a = [2,1,0]
>>> a[0], a[a[0]] = a[a[0]], a[0]
>>> a
[2, 1, 0]
>>> a[0]
2
>>> a[0],a[2] = a[2], a[0]
>>> a
[0, 1, 2]
My guess is that the implementation of a, b = b, a syntax is something like:
tmp = a[0] (tmp = 2)
a[0] = a[a[0]] (a[0] = a[2] = 0)
a[a[0]] = tmp (a[a[0]] = a[0] = tmp = 2)
Then I checked the implementation of swap function in C++. I know nothing about C++, but it looks like the idea is the same
:
http://www.cplusplus.com/reference/algorithm/swap/
The behavior of these function templates is equivalent to:
template <class T> void swap (T& a, T& b)
T c(std::move(a)); a=std::move(b); b=std::move(c);
template <class T, size_t N> void swap (T (&a)[N], T (&b)[N])
for (size_t i = 0; i<N; ++i) swap (a[i],b[i]);
we have c = a, then a = b and b = a
So why C++ swap function does not have this problem?
And how to write this kind of swap function in a pythonic way?
python algorithm
python algorithm
edited Aug 21 at 13:51
Rakete1111
32.6k975110
32.6k975110
asked Aug 21 at 13:46
RioAraki
1465
1465
1
if you use a different list (likea = [1,2,3,4]
) you will see it does change the values, but the problem is in the order of execution, soa[a[0]]
points to different elements the two times its called.
â Zinki
Aug 21 at 13:54
Possible duplicate of Multiple assignment and evaluation order in Python
â agtoever
Aug 21 at 14:04
Fun fact: if you usea = [2,3,4]
instead, you get "List assignment index out of range".
â molbdnilo
Aug 21 at 14:08
I believe there's a problem somewhat related to the "sequence points" problem in C++, in that your left-hand side both modifies and usesa[0]
.
â molbdnilo
Aug 21 at 14:26
add a comment |Â
1
if you use a different list (likea = [1,2,3,4]
) you will see it does change the values, but the problem is in the order of execution, soa[a[0]]
points to different elements the two times its called.
â Zinki
Aug 21 at 13:54
Possible duplicate of Multiple assignment and evaluation order in Python
â agtoever
Aug 21 at 14:04
Fun fact: if you usea = [2,3,4]
instead, you get "List assignment index out of range".
â molbdnilo
Aug 21 at 14:08
I believe there's a problem somewhat related to the "sequence points" problem in C++, in that your left-hand side both modifies and usesa[0]
.
â molbdnilo
Aug 21 at 14:26
1
1
if you use a different list (like
a = [1,2,3,4]
) you will see it does change the values, but the problem is in the order of execution, so a[a[0]]
points to different elements the two times its called.â Zinki
Aug 21 at 13:54
if you use a different list (like
a = [1,2,3,4]
) you will see it does change the values, but the problem is in the order of execution, so a[a[0]]
points to different elements the two times its called.â Zinki
Aug 21 at 13:54
Possible duplicate of Multiple assignment and evaluation order in Python
â agtoever
Aug 21 at 14:04
Possible duplicate of Multiple assignment and evaluation order in Python
â agtoever
Aug 21 at 14:04
Fun fact: if you use
a = [2,3,4]
instead, you get "List assignment index out of range".â molbdnilo
Aug 21 at 14:08
Fun fact: if you use
a = [2,3,4]
instead, you get "List assignment index out of range".â molbdnilo
Aug 21 at 14:08
I believe there's a problem somewhat related to the "sequence points" problem in C++, in that your left-hand side both modifies and uses
a[0]
.â molbdnilo
Aug 21 at 14:26
I believe there's a problem somewhat related to the "sequence points" problem in C++, in that your left-hand side both modifies and uses
a[0]
.â molbdnilo
Aug 21 at 14:26
add a comment |Â
4 Answers
4
active
oldest
votes
up vote
5
down vote
accepted
To understand this you need to go inside the implementation using dis
.
First lets consider a simple swap function:
from dis import dis
def swap(i, j):
i, j = j, i
dis(swap)
Output Byte Code:
4 0 LOAD_FAST 1 (j)
2 LOAD_FAST 0 (i)
4 ROT_TWO
6 STORE_FAST 0 (i)
8 STORE_FAST 1 (j)
10 LOAD_CONST 0 (None)
12 RETURN_VALUE
You can see that there is ROT_TWO which means that
Swaps the two top-most stack items.
This ROT_TWO
is mainly responsible for the swapping.
Now coming to your question:
Lets take the example which is working:
from dis import dis
def swap():
a = [2, 1]
a[0], a[1] = a[1], a[0]
dis(swap)
Output Byte Code :
4 0 LOAD_CONST 1 (2)
2 LOAD_CONST 2 (1)
4 BUILD_LIST 2
6 STORE_FAST 0 (a)
5 8 LOAD_FAST 0 (a)
10 LOAD_CONST 2 (1)
12 BINARY_SUBSCR
14 LOAD_FAST 0 (a)
16 LOAD_CONST 3 (0)
18 BINARY_SUBSCR
20 ROT_TWO
22 LOAD_FAST 0 (a)
24 LOAD_CONST 3 (0)
26 STORE_SUBSCR
28 LOAD_FAST 0 (a)
30 LOAD_CONST 2 (1)
32 STORE_SUBSCR
34 LOAD_CONST 0 (None)
36 RETURN_VALUE
Output byte code is similar to what we have when it is a simple swap function.
But when the code is changed:
from dis import dis
def swap():
a = [1, 0]
a[0], a[a[0]] = a[a[0]], a[0]
dis(swap)
swap()
Output is
4 0 LOAD_CONST 1 (1)
2 LOAD_CONST 2 (0)
4 BUILD_LIST 2
6 STORE_FAST 0 (a)
5 8 LOAD_FAST 0 (a)
10 LOAD_FAST 0 (a)
12 LOAD_CONST 2 (0)
14 BINARY_SUBSCR
16 BINARY_SUBSCR
18 LOAD_FAST 0 (a)
20 LOAD_CONST 2 (0)
22 BINARY_SUBSCR
24 ROT_TWO
26 LOAD_FAST 0 (a)
28 LOAD_CONST 2 (0)
30 STORE_SUBSCR
32 LOAD_FAST 0 (a)
34 LOAD_FAST 0 (a)
36 LOAD_CONST 2 (0)
38 BINARY_SUBSCR
40 STORE_SUBSCR
42 LOAD_CONST 0 (None)
44 RETURN_VALUE
You can see the output byte code that top two items are the same. Hence it doesn't swap
I thinkSwaps the two top-most stack items.
is still not an implementation detail. How do these two items swap?
â Sraw
Aug 21 at 14:03
@Sraw check my updated explanation. I think it would make more sense now
â argo
Aug 21 at 14:23
add a comment |Â
up vote
7
down vote
This kind of the behaviour is indeed related to the way Python evaluates the expression of the type
a,b=b,a
In fact, what Python does is first it "prepares" the values of the right side by creating a tuple (b,a)
. Then this tuple is unpacked and assigned to the variables in the reverse order.
It is important to note that the temporary tuple is created using values of variables (de facto copies of values), not references to the variables (you can read here about the difference between passing by value and by reference).
To break down the example with reference types (lists) that you used:
a = [2,1,0]
a[0], a[a[0]] = a[a[0]], a[0]
a[a[0]]
takes the value from thea[0]
element (equal to2
) of the lista
(value0
).a[0]
is2
hence the tuple created is(0,2)
- Tuple
(0,2)
is unpacked and0
replaces2
in the list (0th element). - Now,
a[a[0]]
can be read as: take 0th element of lista
(which is currently0
) and then replace the value in the list at that place with2
from tuple unpacking (now0
is replaced by2
- which make the operation look like it does nothing to the list).
As suggested in the answer from von Oak
changing the order helps because the step from the point 4. above does not replace the value again.
add a comment |Â
up vote
1
down vote
Python and C++ are different languages with different rules. That's largely the reason why superficially similar constructs behave differently in these languages.
You cannot write a generic swap
in Python that would work with input like a[0], a[a[0]]
. This is not a problem. You shouldn't ever try to swap such things in any language in order to avoid confusion and improve your chances for future employment as a programmer.
If you absolutely positively need to swap array elements indexed by elements of the same array, you can do it like so in Python:
p, q, a[p], a[q] = index0, index1, a[q], a[p]
where index0
and index1
may be any expression involving a[i]
, a[a[i]]
, a[a[a[i]]]
or anything similar. For example
p, q, a[p], a[q] = a[0], a[a[0]], a[q], a[p]
works.
add a comment |Â
up vote
0
down vote
It's easy to think about it also only on the paper (e.g. at the job interview) and you don't need to debug or disassemble code to bytecode for understanding.
I also think it hasn't anything to do with the implementation of swap function in C++. These are unrelated things.
What you only need to know is that the right side is completely evaluated first and then the values from the right side of the expression are assigned to the values on the left side in the order from the left to the right. Sophros answered it right way I only expand the idea further and in more detail.
Imagine the first case. We have:
a = [2,1,0]
a[0], a[a[0]] = a[a[0]], a[0]
When we start to execute this code, the right side evaluates first, so we will have
a[0], a[a[0]] = a[a[0]], a[0] # a[a[0]] == 0, a[0] == 2, a == [2, 1, 0]
On the right side, we have tuple (0, 2)
and a
is still [2, 1, 0]
Next, we start to assign to the left side of the expression from the left, so to the a[0]
we assign the first item from the tuple, which is 0
. Now we have
a[0], a[a[0]] = (0, 2) # a[0] == 0, a == [0, 1, 0]
And now we execute the last part of the assignment, which is to a[a[0]]
assign 2
. But a[0]
is now 0
, so after reduction we assign to a[0]
value 2
. Therefore values after the last assignment are
a[0], a[a[0]] = (0, 2) # a[a[0]] == 2, a == [2, 1, 0]
Which seems, that nothing changed and values didn't swap, but as is apparent from above a
was [2,1,0]
, then [0,1,0]
and lastly again [2,1,0]
. So it seems, nothing changed and swap doesn't work.
And now the second case, where we only change the order of variables in the expression:
a = [2,1,0]
a[a[0]], a[0] = a[0], a[a[0]]
When we start to execute this code, the right side evaluates first, so we will have
a[a[0]], a[0] = a[0], a[a[0]] # a[0] == 2, a[a[0]] == 0, a == [2, 1, 0]
On the right side, we have tuple (2, 0)
and a
is still [2, 1, 0]
Next, we start to assign to the left side of the expression from the left, so to the a[a[0]]
we assign the first item from the tuple, which is 2
. a[0]
is 2
, so after reduction, we assign to a[2]
value 2
. Now we have
a[a[0]], a[0] = (2, 0) # a[a[0]] == 2, a == [2, 1, 2]
And now we execute the last part of the assignment, which is to a[0]
assign 0
. Therefore values after the last assignment are
a[a[0]], a[0] = (2, 0) # a[0] == 0, a == [0, 1, 2]
Now this works as expected.
So it is necessary also think about the order when you have dependent variables in your swap expression. As dependent variables I mean that in the first case we have on the left side a[0], a[a[0]]
that means a[0]
change it's value and a[a[0]]
use this changed value, which leads to unwanted behavior.
Finally, regardless of the programming language, it's better not to use dependent variables (array index for another array index etc.), when you want to swap their values.
What about swappinga[a[a[0]]]
anda[a[0]]
? Would it work?
â n.m.
Aug 21 at 14:22
I vastly extended my answer, so now you can try your example as the exercise:-)
â von Oak
Aug 21 at 23:30
add a comment |Â
4 Answers
4
active
oldest
votes
4 Answers
4
active
oldest
votes
active
oldest
votes
active
oldest
votes
up vote
5
down vote
accepted
To understand this you need to go inside the implementation using dis
.
First lets consider a simple swap function:
from dis import dis
def swap(i, j):
i, j = j, i
dis(swap)
Output Byte Code:
4 0 LOAD_FAST 1 (j)
2 LOAD_FAST 0 (i)
4 ROT_TWO
6 STORE_FAST 0 (i)
8 STORE_FAST 1 (j)
10 LOAD_CONST 0 (None)
12 RETURN_VALUE
You can see that there is ROT_TWO which means that
Swaps the two top-most stack items.
This ROT_TWO
is mainly responsible for the swapping.
Now coming to your question:
Lets take the example which is working:
from dis import dis
def swap():
a = [2, 1]
a[0], a[1] = a[1], a[0]
dis(swap)
Output Byte Code :
4 0 LOAD_CONST 1 (2)
2 LOAD_CONST 2 (1)
4 BUILD_LIST 2
6 STORE_FAST 0 (a)
5 8 LOAD_FAST 0 (a)
10 LOAD_CONST 2 (1)
12 BINARY_SUBSCR
14 LOAD_FAST 0 (a)
16 LOAD_CONST 3 (0)
18 BINARY_SUBSCR
20 ROT_TWO
22 LOAD_FAST 0 (a)
24 LOAD_CONST 3 (0)
26 STORE_SUBSCR
28 LOAD_FAST 0 (a)
30 LOAD_CONST 2 (1)
32 STORE_SUBSCR
34 LOAD_CONST 0 (None)
36 RETURN_VALUE
Output byte code is similar to what we have when it is a simple swap function.
But when the code is changed:
from dis import dis
def swap():
a = [1, 0]
a[0], a[a[0]] = a[a[0]], a[0]
dis(swap)
swap()
Output is
4 0 LOAD_CONST 1 (1)
2 LOAD_CONST 2 (0)
4 BUILD_LIST 2
6 STORE_FAST 0 (a)
5 8 LOAD_FAST 0 (a)
10 LOAD_FAST 0 (a)
12 LOAD_CONST 2 (0)
14 BINARY_SUBSCR
16 BINARY_SUBSCR
18 LOAD_FAST 0 (a)
20 LOAD_CONST 2 (0)
22 BINARY_SUBSCR
24 ROT_TWO
26 LOAD_FAST 0 (a)
28 LOAD_CONST 2 (0)
30 STORE_SUBSCR
32 LOAD_FAST 0 (a)
34 LOAD_FAST 0 (a)
36 LOAD_CONST 2 (0)
38 BINARY_SUBSCR
40 STORE_SUBSCR
42 LOAD_CONST 0 (None)
44 RETURN_VALUE
You can see the output byte code that top two items are the same. Hence it doesn't swap
I thinkSwaps the two top-most stack items.
is still not an implementation detail. How do these two items swap?
â Sraw
Aug 21 at 14:03
@Sraw check my updated explanation. I think it would make more sense now
â argo
Aug 21 at 14:23
add a comment |Â
up vote
5
down vote
accepted
To understand this you need to go inside the implementation using dis
.
First lets consider a simple swap function:
from dis import dis
def swap(i, j):
i, j = j, i
dis(swap)
Output Byte Code:
4 0 LOAD_FAST 1 (j)
2 LOAD_FAST 0 (i)
4 ROT_TWO
6 STORE_FAST 0 (i)
8 STORE_FAST 1 (j)
10 LOAD_CONST 0 (None)
12 RETURN_VALUE
You can see that there is ROT_TWO which means that
Swaps the two top-most stack items.
This ROT_TWO
is mainly responsible for the swapping.
Now coming to your question:
Lets take the example which is working:
from dis import dis
def swap():
a = [2, 1]
a[0], a[1] = a[1], a[0]
dis(swap)
Output Byte Code :
4 0 LOAD_CONST 1 (2)
2 LOAD_CONST 2 (1)
4 BUILD_LIST 2
6 STORE_FAST 0 (a)
5 8 LOAD_FAST 0 (a)
10 LOAD_CONST 2 (1)
12 BINARY_SUBSCR
14 LOAD_FAST 0 (a)
16 LOAD_CONST 3 (0)
18 BINARY_SUBSCR
20 ROT_TWO
22 LOAD_FAST 0 (a)
24 LOAD_CONST 3 (0)
26 STORE_SUBSCR
28 LOAD_FAST 0 (a)
30 LOAD_CONST 2 (1)
32 STORE_SUBSCR
34 LOAD_CONST 0 (None)
36 RETURN_VALUE
Output byte code is similar to what we have when it is a simple swap function.
But when the code is changed:
from dis import dis
def swap():
a = [1, 0]
a[0], a[a[0]] = a[a[0]], a[0]
dis(swap)
swap()
Output is
4 0 LOAD_CONST 1 (1)
2 LOAD_CONST 2 (0)
4 BUILD_LIST 2
6 STORE_FAST 0 (a)
5 8 LOAD_FAST 0 (a)
10 LOAD_FAST 0 (a)
12 LOAD_CONST 2 (0)
14 BINARY_SUBSCR
16 BINARY_SUBSCR
18 LOAD_FAST 0 (a)
20 LOAD_CONST 2 (0)
22 BINARY_SUBSCR
24 ROT_TWO
26 LOAD_FAST 0 (a)
28 LOAD_CONST 2 (0)
30 STORE_SUBSCR
32 LOAD_FAST 0 (a)
34 LOAD_FAST 0 (a)
36 LOAD_CONST 2 (0)
38 BINARY_SUBSCR
40 STORE_SUBSCR
42 LOAD_CONST 0 (None)
44 RETURN_VALUE
You can see the output byte code that top two items are the same. Hence it doesn't swap
I thinkSwaps the two top-most stack items.
is still not an implementation detail. How do these two items swap?
â Sraw
Aug 21 at 14:03
@Sraw check my updated explanation. I think it would make more sense now
â argo
Aug 21 at 14:23
add a comment |Â
up vote
5
down vote
accepted
up vote
5
down vote
accepted
To understand this you need to go inside the implementation using dis
.
First lets consider a simple swap function:
from dis import dis
def swap(i, j):
i, j = j, i
dis(swap)
Output Byte Code:
4 0 LOAD_FAST 1 (j)
2 LOAD_FAST 0 (i)
4 ROT_TWO
6 STORE_FAST 0 (i)
8 STORE_FAST 1 (j)
10 LOAD_CONST 0 (None)
12 RETURN_VALUE
You can see that there is ROT_TWO which means that
Swaps the two top-most stack items.
This ROT_TWO
is mainly responsible for the swapping.
Now coming to your question:
Lets take the example which is working:
from dis import dis
def swap():
a = [2, 1]
a[0], a[1] = a[1], a[0]
dis(swap)
Output Byte Code :
4 0 LOAD_CONST 1 (2)
2 LOAD_CONST 2 (1)
4 BUILD_LIST 2
6 STORE_FAST 0 (a)
5 8 LOAD_FAST 0 (a)
10 LOAD_CONST 2 (1)
12 BINARY_SUBSCR
14 LOAD_FAST 0 (a)
16 LOAD_CONST 3 (0)
18 BINARY_SUBSCR
20 ROT_TWO
22 LOAD_FAST 0 (a)
24 LOAD_CONST 3 (0)
26 STORE_SUBSCR
28 LOAD_FAST 0 (a)
30 LOAD_CONST 2 (1)
32 STORE_SUBSCR
34 LOAD_CONST 0 (None)
36 RETURN_VALUE
Output byte code is similar to what we have when it is a simple swap function.
But when the code is changed:
from dis import dis
def swap():
a = [1, 0]
a[0], a[a[0]] = a[a[0]], a[0]
dis(swap)
swap()
Output is
4 0 LOAD_CONST 1 (1)
2 LOAD_CONST 2 (0)
4 BUILD_LIST 2
6 STORE_FAST 0 (a)
5 8 LOAD_FAST 0 (a)
10 LOAD_FAST 0 (a)
12 LOAD_CONST 2 (0)
14 BINARY_SUBSCR
16 BINARY_SUBSCR
18 LOAD_FAST 0 (a)
20 LOAD_CONST 2 (0)
22 BINARY_SUBSCR
24 ROT_TWO
26 LOAD_FAST 0 (a)
28 LOAD_CONST 2 (0)
30 STORE_SUBSCR
32 LOAD_FAST 0 (a)
34 LOAD_FAST 0 (a)
36 LOAD_CONST 2 (0)
38 BINARY_SUBSCR
40 STORE_SUBSCR
42 LOAD_CONST 0 (None)
44 RETURN_VALUE
You can see the output byte code that top two items are the same. Hence it doesn't swap
To understand this you need to go inside the implementation using dis
.
First lets consider a simple swap function:
from dis import dis
def swap(i, j):
i, j = j, i
dis(swap)
Output Byte Code:
4 0 LOAD_FAST 1 (j)
2 LOAD_FAST 0 (i)
4 ROT_TWO
6 STORE_FAST 0 (i)
8 STORE_FAST 1 (j)
10 LOAD_CONST 0 (None)
12 RETURN_VALUE
You can see that there is ROT_TWO which means that
Swaps the two top-most stack items.
This ROT_TWO
is mainly responsible for the swapping.
Now coming to your question:
Lets take the example which is working:
from dis import dis
def swap():
a = [2, 1]
a[0], a[1] = a[1], a[0]
dis(swap)
Output Byte Code :
4 0 LOAD_CONST 1 (2)
2 LOAD_CONST 2 (1)
4 BUILD_LIST 2
6 STORE_FAST 0 (a)
5 8 LOAD_FAST 0 (a)
10 LOAD_CONST 2 (1)
12 BINARY_SUBSCR
14 LOAD_FAST 0 (a)
16 LOAD_CONST 3 (0)
18 BINARY_SUBSCR
20 ROT_TWO
22 LOAD_FAST 0 (a)
24 LOAD_CONST 3 (0)
26 STORE_SUBSCR
28 LOAD_FAST 0 (a)
30 LOAD_CONST 2 (1)
32 STORE_SUBSCR
34 LOAD_CONST 0 (None)
36 RETURN_VALUE
Output byte code is similar to what we have when it is a simple swap function.
But when the code is changed:
from dis import dis
def swap():
a = [1, 0]
a[0], a[a[0]] = a[a[0]], a[0]
dis(swap)
swap()
Output is
4 0 LOAD_CONST 1 (1)
2 LOAD_CONST 2 (0)
4 BUILD_LIST 2
6 STORE_FAST 0 (a)
5 8 LOAD_FAST 0 (a)
10 LOAD_FAST 0 (a)
12 LOAD_CONST 2 (0)
14 BINARY_SUBSCR
16 BINARY_SUBSCR
18 LOAD_FAST 0 (a)
20 LOAD_CONST 2 (0)
22 BINARY_SUBSCR
24 ROT_TWO
26 LOAD_FAST 0 (a)
28 LOAD_CONST 2 (0)
30 STORE_SUBSCR
32 LOAD_FAST 0 (a)
34 LOAD_FAST 0 (a)
36 LOAD_CONST 2 (0)
38 BINARY_SUBSCR
40 STORE_SUBSCR
42 LOAD_CONST 0 (None)
44 RETURN_VALUE
You can see the output byte code that top two items are the same. Hence it doesn't swap
edited Aug 21 at 14:30
answered Aug 21 at 13:59
argo
2,1231725
2,1231725
I thinkSwaps the two top-most stack items.
is still not an implementation detail. How do these two items swap?
â Sraw
Aug 21 at 14:03
@Sraw check my updated explanation. I think it would make more sense now
â argo
Aug 21 at 14:23
add a comment |Â
I thinkSwaps the two top-most stack items.
is still not an implementation detail. How do these two items swap?
â Sraw
Aug 21 at 14:03
@Sraw check my updated explanation. I think it would make more sense now
â argo
Aug 21 at 14:23
I think
Swaps the two top-most stack items.
is still not an implementation detail. How do these two items swap?â Sraw
Aug 21 at 14:03
I think
Swaps the two top-most stack items.
is still not an implementation detail. How do these two items swap?â Sraw
Aug 21 at 14:03
@Sraw check my updated explanation. I think it would make more sense now
â argo
Aug 21 at 14:23
@Sraw check my updated explanation. I think it would make more sense now
â argo
Aug 21 at 14:23
add a comment |Â
up vote
7
down vote
This kind of the behaviour is indeed related to the way Python evaluates the expression of the type
a,b=b,a
In fact, what Python does is first it "prepares" the values of the right side by creating a tuple (b,a)
. Then this tuple is unpacked and assigned to the variables in the reverse order.
It is important to note that the temporary tuple is created using values of variables (de facto copies of values), not references to the variables (you can read here about the difference between passing by value and by reference).
To break down the example with reference types (lists) that you used:
a = [2,1,0]
a[0], a[a[0]] = a[a[0]], a[0]
a[a[0]]
takes the value from thea[0]
element (equal to2
) of the lista
(value0
).a[0]
is2
hence the tuple created is(0,2)
- Tuple
(0,2)
is unpacked and0
replaces2
in the list (0th element). - Now,
a[a[0]]
can be read as: take 0th element of lista
(which is currently0
) and then replace the value in the list at that place with2
from tuple unpacking (now0
is replaced by2
- which make the operation look like it does nothing to the list).
As suggested in the answer from von Oak
changing the order helps because the step from the point 4. above does not replace the value again.
add a comment |Â
up vote
7
down vote
This kind of the behaviour is indeed related to the way Python evaluates the expression of the type
a,b=b,a
In fact, what Python does is first it "prepares" the values of the right side by creating a tuple (b,a)
. Then this tuple is unpacked and assigned to the variables in the reverse order.
It is important to note that the temporary tuple is created using values of variables (de facto copies of values), not references to the variables (you can read here about the difference between passing by value and by reference).
To break down the example with reference types (lists) that you used:
a = [2,1,0]
a[0], a[a[0]] = a[a[0]], a[0]
a[a[0]]
takes the value from thea[0]
element (equal to2
) of the lista
(value0
).a[0]
is2
hence the tuple created is(0,2)
- Tuple
(0,2)
is unpacked and0
replaces2
in the list (0th element). - Now,
a[a[0]]
can be read as: take 0th element of lista
(which is currently0
) and then replace the value in the list at that place with2
from tuple unpacking (now0
is replaced by2
- which make the operation look like it does nothing to the list).
As suggested in the answer from von Oak
changing the order helps because the step from the point 4. above does not replace the value again.
add a comment |Â
up vote
7
down vote
up vote
7
down vote
This kind of the behaviour is indeed related to the way Python evaluates the expression of the type
a,b=b,a
In fact, what Python does is first it "prepares" the values of the right side by creating a tuple (b,a)
. Then this tuple is unpacked and assigned to the variables in the reverse order.
It is important to note that the temporary tuple is created using values of variables (de facto copies of values), not references to the variables (you can read here about the difference between passing by value and by reference).
To break down the example with reference types (lists) that you used:
a = [2,1,0]
a[0], a[a[0]] = a[a[0]], a[0]
a[a[0]]
takes the value from thea[0]
element (equal to2
) of the lista
(value0
).a[0]
is2
hence the tuple created is(0,2)
- Tuple
(0,2)
is unpacked and0
replaces2
in the list (0th element). - Now,
a[a[0]]
can be read as: take 0th element of lista
(which is currently0
) and then replace the value in the list at that place with2
from tuple unpacking (now0
is replaced by2
- which make the operation look like it does nothing to the list).
As suggested in the answer from von Oak
changing the order helps because the step from the point 4. above does not replace the value again.
This kind of the behaviour is indeed related to the way Python evaluates the expression of the type
a,b=b,a
In fact, what Python does is first it "prepares" the values of the right side by creating a tuple (b,a)
. Then this tuple is unpacked and assigned to the variables in the reverse order.
It is important to note that the temporary tuple is created using values of variables (de facto copies of values), not references to the variables (you can read here about the difference between passing by value and by reference).
To break down the example with reference types (lists) that you used:
a = [2,1,0]
a[0], a[a[0]] = a[a[0]], a[0]
a[a[0]]
takes the value from thea[0]
element (equal to2
) of the lista
(value0
).a[0]
is2
hence the tuple created is(0,2)
- Tuple
(0,2)
is unpacked and0
replaces2
in the list (0th element). - Now,
a[a[0]]
can be read as: take 0th element of lista
(which is currently0
) and then replace the value in the list at that place with2
from tuple unpacking (now0
is replaced by2
- which make the operation look like it does nothing to the list).
As suggested in the answer from von Oak
changing the order helps because the step from the point 4. above does not replace the value again.
answered Aug 21 at 14:07
sophros
1,343416
1,343416
add a comment |Â
add a comment |Â
up vote
1
down vote
Python and C++ are different languages with different rules. That's largely the reason why superficially similar constructs behave differently in these languages.
You cannot write a generic swap
in Python that would work with input like a[0], a[a[0]]
. This is not a problem. You shouldn't ever try to swap such things in any language in order to avoid confusion and improve your chances for future employment as a programmer.
If you absolutely positively need to swap array elements indexed by elements of the same array, you can do it like so in Python:
p, q, a[p], a[q] = index0, index1, a[q], a[p]
where index0
and index1
may be any expression involving a[i]
, a[a[i]]
, a[a[a[i]]]
or anything similar. For example
p, q, a[p], a[q] = a[0], a[a[0]], a[q], a[p]
works.
add a comment |Â
up vote
1
down vote
Python and C++ are different languages with different rules. That's largely the reason why superficially similar constructs behave differently in these languages.
You cannot write a generic swap
in Python that would work with input like a[0], a[a[0]]
. This is not a problem. You shouldn't ever try to swap such things in any language in order to avoid confusion and improve your chances for future employment as a programmer.
If you absolutely positively need to swap array elements indexed by elements of the same array, you can do it like so in Python:
p, q, a[p], a[q] = index0, index1, a[q], a[p]
where index0
and index1
may be any expression involving a[i]
, a[a[i]]
, a[a[a[i]]]
or anything similar. For example
p, q, a[p], a[q] = a[0], a[a[0]], a[q], a[p]
works.
add a comment |Â
up vote
1
down vote
up vote
1
down vote
Python and C++ are different languages with different rules. That's largely the reason why superficially similar constructs behave differently in these languages.
You cannot write a generic swap
in Python that would work with input like a[0], a[a[0]]
. This is not a problem. You shouldn't ever try to swap such things in any language in order to avoid confusion and improve your chances for future employment as a programmer.
If you absolutely positively need to swap array elements indexed by elements of the same array, you can do it like so in Python:
p, q, a[p], a[q] = index0, index1, a[q], a[p]
where index0
and index1
may be any expression involving a[i]
, a[a[i]]
, a[a[a[i]]]
or anything similar. For example
p, q, a[p], a[q] = a[0], a[a[0]], a[q], a[p]
works.
Python and C++ are different languages with different rules. That's largely the reason why superficially similar constructs behave differently in these languages.
You cannot write a generic swap
in Python that would work with input like a[0], a[a[0]]
. This is not a problem. You shouldn't ever try to swap such things in any language in order to avoid confusion and improve your chances for future employment as a programmer.
If you absolutely positively need to swap array elements indexed by elements of the same array, you can do it like so in Python:
p, q, a[p], a[q] = index0, index1, a[q], a[p]
where index0
and index1
may be any expression involving a[i]
, a[a[i]]
, a[a[a[i]]]
or anything similar. For example
p, q, a[p], a[q] = a[0], a[a[0]], a[q], a[p]
works.
edited Aug 21 at 14:38
answered Aug 21 at 13:59
n.m.
68.6k882165
68.6k882165
add a comment |Â
add a comment |Â
up vote
0
down vote
It's easy to think about it also only on the paper (e.g. at the job interview) and you don't need to debug or disassemble code to bytecode for understanding.
I also think it hasn't anything to do with the implementation of swap function in C++. These are unrelated things.
What you only need to know is that the right side is completely evaluated first and then the values from the right side of the expression are assigned to the values on the left side in the order from the left to the right. Sophros answered it right way I only expand the idea further and in more detail.
Imagine the first case. We have:
a = [2,1,0]
a[0], a[a[0]] = a[a[0]], a[0]
When we start to execute this code, the right side evaluates first, so we will have
a[0], a[a[0]] = a[a[0]], a[0] # a[a[0]] == 0, a[0] == 2, a == [2, 1, 0]
On the right side, we have tuple (0, 2)
and a
is still [2, 1, 0]
Next, we start to assign to the left side of the expression from the left, so to the a[0]
we assign the first item from the tuple, which is 0
. Now we have
a[0], a[a[0]] = (0, 2) # a[0] == 0, a == [0, 1, 0]
And now we execute the last part of the assignment, which is to a[a[0]]
assign 2
. But a[0]
is now 0
, so after reduction we assign to a[0]
value 2
. Therefore values after the last assignment are
a[0], a[a[0]] = (0, 2) # a[a[0]] == 2, a == [2, 1, 0]
Which seems, that nothing changed and values didn't swap, but as is apparent from above a
was [2,1,0]
, then [0,1,0]
and lastly again [2,1,0]
. So it seems, nothing changed and swap doesn't work.
And now the second case, where we only change the order of variables in the expression:
a = [2,1,0]
a[a[0]], a[0] = a[0], a[a[0]]
When we start to execute this code, the right side evaluates first, so we will have
a[a[0]], a[0] = a[0], a[a[0]] # a[0] == 2, a[a[0]] == 0, a == [2, 1, 0]
On the right side, we have tuple (2, 0)
and a
is still [2, 1, 0]
Next, we start to assign to the left side of the expression from the left, so to the a[a[0]]
we assign the first item from the tuple, which is 2
. a[0]
is 2
, so after reduction, we assign to a[2]
value 2
. Now we have
a[a[0]], a[0] = (2, 0) # a[a[0]] == 2, a == [2, 1, 2]
And now we execute the last part of the assignment, which is to a[0]
assign 0
. Therefore values after the last assignment are
a[a[0]], a[0] = (2, 0) # a[0] == 0, a == [0, 1, 2]
Now this works as expected.
So it is necessary also think about the order when you have dependent variables in your swap expression. As dependent variables I mean that in the first case we have on the left side a[0], a[a[0]]
that means a[0]
change it's value and a[a[0]]
use this changed value, which leads to unwanted behavior.
Finally, regardless of the programming language, it's better not to use dependent variables (array index for another array index etc.), when you want to swap their values.
What about swappinga[a[a[0]]]
anda[a[0]]
? Would it work?
â n.m.
Aug 21 at 14:22
I vastly extended my answer, so now you can try your example as the exercise:-)
â von Oak
Aug 21 at 23:30
add a comment |Â
up vote
0
down vote
It's easy to think about it also only on the paper (e.g. at the job interview) and you don't need to debug or disassemble code to bytecode for understanding.
I also think it hasn't anything to do with the implementation of swap function in C++. These are unrelated things.
What you only need to know is that the right side is completely evaluated first and then the values from the right side of the expression are assigned to the values on the left side in the order from the left to the right. Sophros answered it right way I only expand the idea further and in more detail.
Imagine the first case. We have:
a = [2,1,0]
a[0], a[a[0]] = a[a[0]], a[0]
When we start to execute this code, the right side evaluates first, so we will have
a[0], a[a[0]] = a[a[0]], a[0] # a[a[0]] == 0, a[0] == 2, a == [2, 1, 0]
On the right side, we have tuple (0, 2)
and a
is still [2, 1, 0]
Next, we start to assign to the left side of the expression from the left, so to the a[0]
we assign the first item from the tuple, which is 0
. Now we have
a[0], a[a[0]] = (0, 2) # a[0] == 0, a == [0, 1, 0]
And now we execute the last part of the assignment, which is to a[a[0]]
assign 2
. But a[0]
is now 0
, so after reduction we assign to a[0]
value 2
. Therefore values after the last assignment are
a[0], a[a[0]] = (0, 2) # a[a[0]] == 2, a == [2, 1, 0]
Which seems, that nothing changed and values didn't swap, but as is apparent from above a
was [2,1,0]
, then [0,1,0]
and lastly again [2,1,0]
. So it seems, nothing changed and swap doesn't work.
And now the second case, where we only change the order of variables in the expression:
a = [2,1,0]
a[a[0]], a[0] = a[0], a[a[0]]
When we start to execute this code, the right side evaluates first, so we will have
a[a[0]], a[0] = a[0], a[a[0]] # a[0] == 2, a[a[0]] == 0, a == [2, 1, 0]
On the right side, we have tuple (2, 0)
and a
is still [2, 1, 0]
Next, we start to assign to the left side of the expression from the left, so to the a[a[0]]
we assign the first item from the tuple, which is 2
. a[0]
is 2
, so after reduction, we assign to a[2]
value 2
. Now we have
a[a[0]], a[0] = (2, 0) # a[a[0]] == 2, a == [2, 1, 2]
And now we execute the last part of the assignment, which is to a[0]
assign 0
. Therefore values after the last assignment are
a[a[0]], a[0] = (2, 0) # a[0] == 0, a == [0, 1, 2]
Now this works as expected.
So it is necessary also think about the order when you have dependent variables in your swap expression. As dependent variables I mean that in the first case we have on the left side a[0], a[a[0]]
that means a[0]
change it's value and a[a[0]]
use this changed value, which leads to unwanted behavior.
Finally, regardless of the programming language, it's better not to use dependent variables (array index for another array index etc.), when you want to swap their values.
What about swappinga[a[a[0]]]
anda[a[0]]
? Would it work?
â n.m.
Aug 21 at 14:22
I vastly extended my answer, so now you can try your example as the exercise:-)
â von Oak
Aug 21 at 23:30
add a comment |Â
up vote
0
down vote
up vote
0
down vote
It's easy to think about it also only on the paper (e.g. at the job interview) and you don't need to debug or disassemble code to bytecode for understanding.
I also think it hasn't anything to do with the implementation of swap function in C++. These are unrelated things.
What you only need to know is that the right side is completely evaluated first and then the values from the right side of the expression are assigned to the values on the left side in the order from the left to the right. Sophros answered it right way I only expand the idea further and in more detail.
Imagine the first case. We have:
a = [2,1,0]
a[0], a[a[0]] = a[a[0]], a[0]
When we start to execute this code, the right side evaluates first, so we will have
a[0], a[a[0]] = a[a[0]], a[0] # a[a[0]] == 0, a[0] == 2, a == [2, 1, 0]
On the right side, we have tuple (0, 2)
and a
is still [2, 1, 0]
Next, we start to assign to the left side of the expression from the left, so to the a[0]
we assign the first item from the tuple, which is 0
. Now we have
a[0], a[a[0]] = (0, 2) # a[0] == 0, a == [0, 1, 0]
And now we execute the last part of the assignment, which is to a[a[0]]
assign 2
. But a[0]
is now 0
, so after reduction we assign to a[0]
value 2
. Therefore values after the last assignment are
a[0], a[a[0]] = (0, 2) # a[a[0]] == 2, a == [2, 1, 0]
Which seems, that nothing changed and values didn't swap, but as is apparent from above a
was [2,1,0]
, then [0,1,0]
and lastly again [2,1,0]
. So it seems, nothing changed and swap doesn't work.
And now the second case, where we only change the order of variables in the expression:
a = [2,1,0]
a[a[0]], a[0] = a[0], a[a[0]]
When we start to execute this code, the right side evaluates first, so we will have
a[a[0]], a[0] = a[0], a[a[0]] # a[0] == 2, a[a[0]] == 0, a == [2, 1, 0]
On the right side, we have tuple (2, 0)
and a
is still [2, 1, 0]
Next, we start to assign to the left side of the expression from the left, so to the a[a[0]]
we assign the first item from the tuple, which is 2
. a[0]
is 2
, so after reduction, we assign to a[2]
value 2
. Now we have
a[a[0]], a[0] = (2, 0) # a[a[0]] == 2, a == [2, 1, 2]
And now we execute the last part of the assignment, which is to a[0]
assign 0
. Therefore values after the last assignment are
a[a[0]], a[0] = (2, 0) # a[0] == 0, a == [0, 1, 2]
Now this works as expected.
So it is necessary also think about the order when you have dependent variables in your swap expression. As dependent variables I mean that in the first case we have on the left side a[0], a[a[0]]
that means a[0]
change it's value and a[a[0]]
use this changed value, which leads to unwanted behavior.
Finally, regardless of the programming language, it's better not to use dependent variables (array index for another array index etc.), when you want to swap their values.
It's easy to think about it also only on the paper (e.g. at the job interview) and you don't need to debug or disassemble code to bytecode for understanding.
I also think it hasn't anything to do with the implementation of swap function in C++. These are unrelated things.
What you only need to know is that the right side is completely evaluated first and then the values from the right side of the expression are assigned to the values on the left side in the order from the left to the right. Sophros answered it right way I only expand the idea further and in more detail.
Imagine the first case. We have:
a = [2,1,0]
a[0], a[a[0]] = a[a[0]], a[0]
When we start to execute this code, the right side evaluates first, so we will have
a[0], a[a[0]] = a[a[0]], a[0] # a[a[0]] == 0, a[0] == 2, a == [2, 1, 0]
On the right side, we have tuple (0, 2)
and a
is still [2, 1, 0]
Next, we start to assign to the left side of the expression from the left, so to the a[0]
we assign the first item from the tuple, which is 0
. Now we have
a[0], a[a[0]] = (0, 2) # a[0] == 0, a == [0, 1, 0]
And now we execute the last part of the assignment, which is to a[a[0]]
assign 2
. But a[0]
is now 0
, so after reduction we assign to a[0]
value 2
. Therefore values after the last assignment are
a[0], a[a[0]] = (0, 2) # a[a[0]] == 2, a == [2, 1, 0]
Which seems, that nothing changed and values didn't swap, but as is apparent from above a
was [2,1,0]
, then [0,1,0]
and lastly again [2,1,0]
. So it seems, nothing changed and swap doesn't work.
And now the second case, where we only change the order of variables in the expression:
a = [2,1,0]
a[a[0]], a[0] = a[0], a[a[0]]
When we start to execute this code, the right side evaluates first, so we will have
a[a[0]], a[0] = a[0], a[a[0]] # a[0] == 2, a[a[0]] == 0, a == [2, 1, 0]
On the right side, we have tuple (2, 0)
and a
is still [2, 1, 0]
Next, we start to assign to the left side of the expression from the left, so to the a[a[0]]
we assign the first item from the tuple, which is 2
. a[0]
is 2
, so after reduction, we assign to a[2]
value 2
. Now we have
a[a[0]], a[0] = (2, 0) # a[a[0]] == 2, a == [2, 1, 2]
And now we execute the last part of the assignment, which is to a[0]
assign 0
. Therefore values after the last assignment are
a[a[0]], a[0] = (2, 0) # a[0] == 0, a == [0, 1, 2]
Now this works as expected.
So it is necessary also think about the order when you have dependent variables in your swap expression. As dependent variables I mean that in the first case we have on the left side a[0], a[a[0]]
that means a[0]
change it's value and a[a[0]]
use this changed value, which leads to unwanted behavior.
Finally, regardless of the programming language, it's better not to use dependent variables (array index for another array index etc.), when you want to swap their values.
edited Aug 21 at 23:36
answered Aug 21 at 13:53
von Oak
753313
753313
What about swappinga[a[a[0]]]
anda[a[0]]
? Would it work?
â n.m.
Aug 21 at 14:22
I vastly extended my answer, so now you can try your example as the exercise:-)
â von Oak
Aug 21 at 23:30
add a comment |Â
What about swappinga[a[a[0]]]
anda[a[0]]
? Would it work?
â n.m.
Aug 21 at 14:22
I vastly extended my answer, so now you can try your example as the exercise:-)
â von Oak
Aug 21 at 23:30
What about swapping
a[a[a[0]]]
and a[a[0]]
? Would it work?â n.m.
Aug 21 at 14:22
What about swapping
a[a[a[0]]]
and a[a[0]]
? Would it work?â n.m.
Aug 21 at 14:22
I vastly extended my answer, so now you can try your example as the exercise:-)
â von Oak
Aug 21 at 23:30
I vastly extended my answer, so now you can try your example as the exercise:-)
â von Oak
Aug 21 at 23:30
add a comment |Â
Sign up or log in
StackExchange.ready(function ()
StackExchange.helpers.onClickDraftSave('#login-link');
);
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
StackExchange.ready(
function ()
StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fstackoverflow.com%2fquestions%2f51950193%2fpython-a-b-b-a-implementation-how-is-it-different-from-c-swap-function%23new-answer', 'question_page');
);
Post as a guest
Sign up or log in
StackExchange.ready(function ()
StackExchange.helpers.onClickDraftSave('#login-link');
);
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Sign up or log in
StackExchange.ready(function ()
StackExchange.helpers.onClickDraftSave('#login-link');
);
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Sign up or log in
StackExchange.ready(function ()
StackExchange.helpers.onClickDraftSave('#login-link');
);
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
1
if you use a different list (like
a = [1,2,3,4]
) you will see it does change the values, but the problem is in the order of execution, soa[a[0]]
points to different elements the two times its called.â Zinki
Aug 21 at 13:54
Possible duplicate of Multiple assignment and evaluation order in Python
â agtoever
Aug 21 at 14:04
Fun fact: if you use
a = [2,3,4]
instead, you get "List assignment index out of range".â molbdnilo
Aug 21 at 14:08
I believe there's a problem somewhat related to the "sequence points" problem in C++, in that your left-hand side both modifies and uses
a[0]
.â molbdnilo
Aug 21 at 14:26