0

I tried in the snippet below:

a, b = a[b] = {}, 5
print('a={0},b={1}'.format(a,b))

The IDE spits out the follows:

a={5: ({...}, 5)},b=5

I have tried S3DEV's advice and execute:

from dis import dis
dis('a, b = a[b] = {}, 5')

And it gives me the follows:

  1       0 BUILD_MAP                0
          2 LOAD_CONST               0 (5)
          4 BUILD_TUPLE              2
          6 DUP_TOP
          8 UNPACK_SEQUENCE          2
         10 STORE_NAME               0 (a)
         12 STORE_NAME               1 (b)
         14 LOAD_NAME                0 (a)
         16 LOAD_NAME                1 (b)
         18 STORE_SUBSCR
         20 LOAD_CONST               1 (None)
         22 RETURN_VALUE

But I still cannot understand why a[b] = a, 5 happened in the step 18 STORE_SUBSCR. Any further explanation?

Jimmy Zhao
  • 303
  • 2
  • 17
  • Comments are not for extended discussion; this conversation has been [moved to chat](https://chat.stackoverflow.com/rooms/244277/discussion-on-question-by-jimmy-zhao-how-to-understand-a-b-ab-5-in-py). – deceze Apr 28 '22 at 08:22
  • 1
    If you'd like to see the bytecode leading to the assignment, you can use: `from dis import dis`, then `dis('a, b = a[b] = {}, 5')`. This will show the steps taken to parse and execute this statement. – S3DEV Apr 28 '22 at 08:31
  • Does this answer your question? [What does \`{...}\` mean in the print output of a python variable?](https://stackoverflow.com/questions/32408387/what-does-mean-in-the-print-output-of-a-python-variable) – shree.pat18 Apr 28 '22 at 08:34

1 Answers1

4

This is an assignment statement with multiple target_list:s, for which case the docs say that the statement "assigns the single resulting object to each of the target lists, from left to right." Within each target_list, assignments also proceed left to right.

Thus, the statement is equivalent to

a = {}
b = 5
a[b] = a, 5

The reason that the last assignment is a[b]=a,5 and not a,b={},5 is that the value ({}, 5) is only evaluated once, so it's the same dict that gets used throughout. First, a is set to refer to that dict, then the dict — through a — is modified to refer to itself.

EDIT: Perhaps it is clearer to say that the statement is equivalent to

temp1 = {}
temp2 = 5
a = temp1
b = temp2
a[b] = temp1, temp2

Right before the last step, a and temp1 refer to the same object, which thus becomes self-referring after the last step.

This is not code I want to see in production. :)

Ture Pålsson
  • 6,088
  • 2
  • 12
  • 15
  • Nice answer. Perhaps include the statement from the docs "Assignment is defined recursively ..." which is why the ellipsis is populated to the dict. – S3DEV Apr 28 '22 at 08:52