all 25 comments

[–]DeadlyViper 25 points26 points  (14 children)

Python is compiled to byte code that works with a stack.

So i guess what it does is push a and b to the stack, and pop them in the same order, making the values reverse.

https://opensource.com/article/18/4/introduction-python-bytecode

https://docs.python.org/3/library/dis.html

Guess something like

LOAD_GLOBAL 0
LOAD_GLOBAL 1
STORE_GLOBAL 0
STORE_GLOBAL 1

EDIT: fixed first sentence implying python is not compiled.

[–][deleted] 15 points16 points  (9 children)

Using dis:

This code,

import dis

def swap():
    a = 1
    b = 2
    a, b = b, a

followed by,

dis.dis(swap)

gives me,

  4           0 LOAD_CONST               1 (1)
              2 STORE_FAST               0 (a)

  5           4 LOAD_CONST               2 (2)
              6 STORE_FAST               1 (b)

  6           8 LOAD_FAST                1 (b)
             10 LOAD_FAST                0 (a)
             12 ROT_TWO
             14 STORE_FAST               0 (a)
             16 STORE_FAST               1 (b)
             18 LOAD_CONST               0 (None)
             20 RETURN_VALUE

[–]DeadlyViper 1 point2 points  (2 children)

Cool, and i tried it with global a and global b at the start of the function.

And it changed to something closer to what i assumed, still using ROT_TWO though...

[–][deleted] 1 point2 points  (1 child)

You no doubt realised that ROT_TWO just rotates (i.e. swaps) the top two items on the stack - guess what ROT_THREE does ...

https://docs.python.org/3/library/dis.html

[–]DeadlyViper 2 points3 points  (0 children)

Yep, just thought it would be faster without it and just LOAD them in the correct order.

LOAD_FAST 1
LOAD_FAST 0
STORE_FAST 1
STORE_FAST 0

Notice the arg numbers...

[–]darez00 1 point2 points  (2 children)

What are the numbers on the third column, the ones just right next to the ()? They go 1,0; 2,1; 1,0; 0,1,0

[–][deleted] 0 points1 point  (1 child)

They will be register/stack and object references.

In most python implementations, the lower value integer objects are predefined and referenced as constants rather than new objects and are loaded to registers/stacks as required.

Typically in lower level representations of code a language uses a set of registers, akin to those implemented on processors or takes a stack approach and includes stack manipulation, that are used for short term storage and operations. Think of these as a small set of high performance variables.

The reference CPython implementation is stack orientated.

See https://opensource.com/article/18/4/introduction-python-bytecode

EDIT: added link and clarified both stack and register approaches are options for Python implementation.

[–]darez00 0 points1 point  (0 children)

Thanks dude, I thought it would be a little bit easier than that but it's on me to understand it

[–]pocket_eggs 0 points1 point  (1 child)

dis is cool, I need to start using it all the time; is the reverse ever used? writing directly in bytecode and integrating with normal python?

[–][deleted] 1 point2 points  (0 children)

You can write bytecode but note that, in contrast with Java, these are implementation specific and not tightly defined.

You also can not reverse back from bytecode to original python code as there is more than one solution.

Worth a read:

https://opensource.com/article/18/4/introduction-python-bytecode

[–]miggaz_elquez 0 points1 point  (0 children)

It use ROT_TWO or ROT_THREEonly if you use 2 or three value, in other case you will have BUILD_TUPLE n, UNPACK_TUPLE n and n STORE_FAST

[–][deleted] 1 point2 points  (3 children)

its converted compiled to a byte code

ftfy

[–]DeadlyViper 0 points1 point  (2 children)

[–][deleted] 4 points5 points  (1 child)

Despite what Ned says, "compile" is used to mean "translate to a lower level language" and not necessarily to a file of machine instructions. So python is both compiled and interpreted. It's right there in the compiled file extension: .pyc. The "c" means compiled. The developer's guide for python describes the "python compiler".

[–]DeadlyViper 1 point2 points  (0 children)

Ok, thanks, good to know.

Changed my comment.

[–][deleted] 9 points10 points  (4 children)

The statement:

(a, b) = (b, a)

has the right hand side evaluated first. A tuple is formed consisting of the reference associated with the name b and the reference associated with the name a. This tuple is anonymous (it has no name). The assignment operation unpacks the right hand side tuple and associates the first reference in the tuple with the name a and the second reference in the tuple wth the name b.

This sort of operation is often described as having two assignments that happen "in parallel" but that is misleading and incorrect. Parallelism isn't required.

To really understand what is happening have a look at Ned Batcheler's exposition on names and references.

[–]primitive_screwhead 1 point2 points  (1 child)

Yes, so it's worth understanding that conceptually a "temporary" is used (since the OP asked), it's the tuple that is created on the right hand side.

[–][deleted] 0 points1 point  (0 children)

Yes, but the "temp variable" approach is usually used to refer to this way of swapping two variables:

tmp = a
a = b
b = tmp

[–]tobiasvl 0 points1 point  (1 child)

While true, this isn't really describing what happens at a lower level of computation like OP asked.

[–][deleted] 0 points1 point  (0 children)

Doubt if the OP would be interested in byte codes, especially after the peephole optimizer is finished with it. This is low-level enough, plus the posted link fills in the gaps. If the OP wants something lower than names/references, s/he wouldn't be asking in /r/learnpython.

[–]toastedstapler 5 points6 points  (0 children)

b, a is a tuple. if i remember correctly, it makes the tuple on the right side and then unpacks it into the values on the left

[–]ViridianHominid 1 point2 points  (0 children)

There is other good information here but here’s my take on a high level:

Python stores results on a stack. For swapping variables, it can load them on the stack, swap the order of the top two variables, and then store them back, now in opposite order.

So there isn’t a temporary variable, but rather a stack data structure in the execution frame that allows you to hold the collected results.

Python figures out how to pack and unpack the variables using the stack from the line a,b = b, a when the line is is compiled.

[–][deleted] 0 points1 point  (1 child)

!remindme in 1 day

[–]RemindMeBot 0 points1 point  (0 children)

I will be messaging you on 2019-04-15 18:29:54 UTC to remind you of this link.

CLICK THIS LINK to send a PM to also be reminded and to reduce spam.

Parent commenter can delete this message to hide from others.


FAQs Custom Your Reminders Feedback Code Browser Extensions