如果声明与表达

时间:2013-09-30 08:57:45

标签: python performance if-statement toggle expression

如果您需要在一个周期内将变量值在0和1之间切换,您更喜欢性能(内存消耗,速度)/ 可读性

x=get(x) 
for i in range (start, end):
    if x==0:
        x=1
    else:
        x=0

x=get(x)
for i in range (start, end):
    x = ((x + 1) % 2)

python编译器如何解释它?

2 个答案:

答案 0 :(得分:4)

除了您使用的if语句和表达式之外,还有很多选项。

  • 使用减法:

    x = 1 - x
    
  • 使用^(XOR):

    for i in range (start, end):
        x ^= 1
    

    这在0和1之间切换:

    >>> x = 1
    >>> x ^ 1
    0
    >>> x ^= 1
    >>> x ^ 1
    1
    
  • 您可以使用itertools.cycle()

    from itertools import cycle
    
    x_values = cycle((0, 1))
    
    for i in range (start, end):
        x = next(x_values)
    

    cycle()对于在多个值之间进行交换特别有用,尤其是当它们之间没有简单的数学或逻辑关系时:

    >>> from itertools import cycle
    >>> x_values = cycle((1, 'spam', 3.14))
    >>> next(x_values)
    1
    >>> next(x_values)
    'spam'
    >>> next(x_values)
    3.14
    >>> next(x_values)
    1
    

但要找出最适合你的方法,选择一个指标并坚持下去。为了提高性能,请使用timeit module进行比较试验。

使用x - 1远远快于cycle()或您的表达式,例如:

>>> from timeit import timeit
>>> timeit('x = 1 - x', 'x = 0')
0.044335126876831055
>>> timeit('x ^= 1', 'x = 0')
0.05133986473083496
>>> timeit('x = ((x + 1) % 2)', 'x = 0')
0.11392998695373535
>>> timeit('x = next(x_values)', 'from itertools import cycle; x_values = cycle((0, 1))')
0.1254570484161377

Python编译器主要解释代码非常简单。例如,您的if版本不会被优化。使用dis.dis() function查看编译器输出的反汇编:

>>> import dis
>>> def foo():
...     if x==0:
...         x=1
...     else:
...         x=0
... 
>>> dis.dis(foo)
  2           0 LOAD_FAST                0 (x)
              3 LOAD_CONST               1 (0)
              6 COMPARE_OP               2 (==)
              9 POP_JUMP_IF_FALSE       21

  3          12 LOAD_CONST               2 (1)
             15 STORE_FAST               0 (x)
             18 JUMP_FORWARD             6 (to 27)

  5     >>   21 LOAD_CONST               1 (0)
             24 STORE_FAST               0 (x)
        >>   27 LOAD_CONST               0 (None)
             30 RETURN_VALUE        

正如您所见,完整的分支结构仍然存在。使用表达式会导致字节码非常不同:

>>> def bar():
...     x = ((x + 1) % 2)
... 
>>> dis.dis(bar)
  2           0 LOAD_FAST                0 (x)
              3 LOAD_CONST               1 (1)
              6 BINARY_ADD          
              7 LOAD_CONST               2 (2)
             10 BINARY_MODULO       
             11 STORE_FAST               0 (x)
             14 LOAD_CONST               0 (None)
             17 RETURN_VALUE        

答案 1 :(得分:0)

您可以使用xor运算符^01之间切换:

x ^= 1