On Tue, Apr 6, 2021 at 2:32 AM Rob Cliffe via Python-list <python-list@python.org> wrote: > > > > It doesn't appear to, at least not always. In Python 3.8.3: > from dis import dis > def f(): x = 1 ; y = 2 > def g(): (x,y) = (1,2) > dis(f) > dis(g) > > Output: > 2 0 LOAD_CONST 1 (1) > 2 STORE_FAST 0 (x) > 4 LOAD_CONST 2 (2) > 6 STORE_FAST 1 (y) > 8 LOAD_CONST 0 (None) > 10 RETURN_VALUE > 3 0 LOAD_CONST 1 ((1, 2)) > 2 UNPACK_SEQUENCE 2 > 4 STORE_FAST 0 (x) > 6 STORE_FAST 1 (y) > 8 LOAD_CONST 0 (None) > 10 RETURN_VALUE > Thinking some more about this, this (removing the tuples) is not a > straightforward optimisation to do.
It's important to be aware of the semantics here. Saying "x = 1; y = 2" requires that x be set before 2 is calculated (imagine if it had been "y = x + 2" or something), whereas "x, y = 1, 2" has to do the opposite, fully evaluating the right hand side before doing any of the assignments. > I guess it's safe if the RHS is a tuple containing only > constants, by which I think I mean number/string literals and > built-in constants (None, True etc.). > variables (NOT expressions containing variables such as "z+1") > which do not occur on the LHS > tuple/list/dictionary/set displays which themselves contain only > the above, or nested displays which themselves ... etc. Nope, there's no "it's safe if" other than constants - which are already handled differently. If there is ANY Python code executed to calculate those values, it could depend on the previous assignments being completed. But the tuples aren't a problem here. They're a highly optimized way of grabbing multiple things at once. In the "x, y = 1, 2" case, the compiler would be free to implement it as "LOAD_CONST 1, LOAD_CONST 2, ROT_TWO, STORE_FAST x, STORE_FAST y" (equivalent to what you'd see for "x, y = y, x"), but it doesn't, so we can fairly confidently expect that the tuple is faster. BTW, if you want to play around with CPython's optimizations, there's another case to consider: def f(): x = y = 1 1 0 LOAD_CONST 1 (1) 2 DUP_TOP 4 STORE_FAST 0 (x) 6 STORE_FAST 1 (y) The constant gets loaded once (which is semantically important), and then duplicated on the stack, leaving two available for storing. Feel free to play around with different combinations here. For instance, "x, y = a, b = 1, 2" should now be unsurprising, but perhaps there'll be some more complicated examples that are interesting to explore. I love dis stuff. :) ChrisA -- https://mail.python.org/mailman/listinfo/python-list