python - Tuple or list when using 'in' in an 'if' clause? -


which approach better? using tuple, like:

if number in (1, 2): 

or list, like:

if number in [1, 2]: 

which 1 recommended such uses , why (both logical , performance wise)?

the cpython interpreter replaces second form first.

that's because loading tuple constant 1 operation, list 3 operations; load 2 integer contents , build new list object.

because using list literal isn't otherwise reachable, substituted tuple:

>>> import dis >>> dis.dis(compile('number in [1, 2]', '<stdin>', 'eval'))   1           0 load_name                0 (number)               3 load_const               2 ((1, 2))               6 compare_op               6 (in)               9 return_value         

here second bytecode loads (1, 2) tuple constant, in one step. compare creating list object not used in membership test:

>>> dis.dis(compile('[1, 2]', '<stdin>', 'eval'))   1           0 load_const               0 (1)               3 load_const               1 (2)               6 build_list               2               9 return_value         

here n+1 steps required list object of length n.

this substitution cpython-specific peephole optimisation; see python/peephole.c source. other python implementations then, want stick immutable objects instead.

that said, best option when using python 3.2 , up, use set literal:

if number in {1, 2}: 

as peephole optimiser replace frozenset() object , membership tests against sets o(1) constant operations:

>>> dis.dis(compile('number in {1, 2}', '<stdin>', 'eval'))   1           0 load_name                0 (number)               3 load_const               2 (frozenset({1, 2}))               6 compare_op               6 (in)               9 return_value 

this optimization added in python 3.2 wasn't backported python 2.

as such, python 2 optimiser doesn't recognize option , cost of building either set or frozenset contents guaranteed more costly using tuple test.

set membership tests o(1) , fast; testing against tuple o(n) worst case. although testing agains set has calculate hash (higher constant cost), cost testing against tuple other first element going higher. on average, sets faster:

>>> import timeit >>> timeit.timeit('1 in (1, 3, 5)', number=10**7)  # best-case tuples 0.21154764899984002 >>> timeit.timeit('8 in (1, 3, 5)', number=10**7)  # worst-case tuples 0.5670104179880582 >>> timeit.timeit('1 in {1, 3, 5}', number=10**7)  # average-case sets 0.2663505630043801 >>> timeit.timeit('8 in {1, 3, 5}', number=10**7)  # worst-case sets 0.25939063701662235 

Comments

Popular posts from this blog

javascript - Jquery show_hide, what to add in order to make the page scroll to the bottom of the hidden field once button is clicked -

javascript - Highcharts multi-color line -

javascript - Enter key does not work in search box -