If I assign a variable to its own value like this (line 2) (after previously assigning a value):
a_list = ['a', 'list']
a_list = a_list
Does this compile down to an actual assignment or is it just skipped?
I'm asking because I want to know whether the latter of the two following code snippets suffers from a performance penalty.
def foo(a_list: list = None):
if a_list is None:
a_list = ['default', 'list', 'values']
def foo(a_list: list = None):
a_list = ['default', 'list', 'values'] if a_list is None else a_list
CodePudding user response:
It is possible to verify the generated bytecode for both methods by yourself with the dis.dis
call. (check @petrch `s answer)
However, the "cost" of the identity assignment will be negligible, compared to other resources your full code will be using, whatever they are: this sort of micro-optimization is not meant to be done in Python code: if CPU cycles count to this level, you should be using a language that maps directly to CPU ops, like C, GO or Rust.
That said, the first form, even taking one extra line and indentation level, is "easier to read". I'd go with the first form. Just the fact that the one-liner may divert the though train in a "maybe this is less performant" thread is not worth it (as is demonstrated by you getting to the point of asking this question)
CodePudding user response:
You can easily check it for yourself with the help of the dis
module. The result may (and will probably) change across python versions:
https://docs.python.org/3/library/dis.html
import dis
>>> def foo(a_list: list = None):
... a_list = ['default', 'list', 'values'] if a_list is None else a_list
...
>>> dis.dis(foo)
2 0 LOAD_FAST 0 (a_list)
2 LOAD_CONST 0 (None)
4 COMPARE_OP 8 (is)
6 POP_JUMP_IF_FALSE 18
8 LOAD_CONST 1 ('default')
10 LOAD_CONST 2 ('list')
12 LOAD_CONST 3 ('values')
14 BUILD_LIST 3
16 JUMP_FORWARD 2 (to 20)
>> 18 LOAD_FAST 0 (a_list)
>> 20 STORE_FAST 0 (a_list)
22 LOAD_CONST 0 (None)
24 RETURN_VALUE
>>> def foo(a_list: list = None):
... if a_list is None:
... a_list = ['default', 'list', 'values']
...
>>> dis.dis(foo)
2 0 LOAD_FAST 0 (a_list)
2 LOAD_CONST 0 (None)
4 COMPARE_OP 8 (is)
6 POP_JUMP_IF_FALSE 18
3 8 LOAD_CONST 1 ('default')
10 LOAD_CONST 2 ('list')
12 LOAD_CONST 3 ('values')
14 BUILD_LIST 3
16 STORE_FAST 0 (a_list)
>> 18 LOAD_CONST 0 (None)
20 RETURN_VALUE