如果a == b或a == c:vs if in {b,c}:

时间:2017-08-21 15:03:10

标签: python

在我的代码中,我经常比较if a == b or a == c or a == d:这样的比较。在某些时候,我发现如果值不可清除,可以很容易地将这些缩短为if a in {b, c, d}:if a in (b, c, d):。但是,我从来没有在其他任何人的代码中看到过这样的结构。这可能是因为:

  1. ==方式较慢。
  2. ==方式更加pythonic。
  3. 他们实际上做了微妙的不同。
  4. 我偶然没有查看任何需要的代码。
  5. 我已经看过了,只是忽略或忘记了它。
  6. 一个人不应该像这样进行比较,因为其他地方的代码应该更好。
  7. 除了我以外,没有人想到in方式。
  8. 是什么原因,如果有的话?

3 个答案:

答案 0 :(得分:4)

对于简单值(即不是表达式或NaN s),if a == b or a == cif a in <iterable of b and c>是等价的。

如果值是可清除的,最好将in set literal 一起使用,而不是使用元组或列表文字:

if a in {b, c}: ...

CPython的peephole optimiser通常能够用缓存的frozenset()对象替换它,对集合的成员资格测试是O(1)操作。

答案 1 :(得分:2)

Performancewise:&#34; in&#34;更好

timeit.timeit("pub='1'; pub == 1 or pub == '1'")
0.07568907737731934
timeit.timeit("pub='1'; pub in[1, '1']")
0.04272890090942383
timeit.timeit("pub=1; pub == 1 or pub == '1'")
0.07502007484436035
timeit.timeit("pub=1; pub in[1, '1']")
0.07035684585571289

另外&#34;在&#34;确保代码不重复== 1或a == 2是重复。 而且阅读不好。 &#34;在&#34;只是让它更容易理解。这是简单而优雅的代码实践的案例之一。简而言之,我们(应该)使用&#34;&#34;更常见的是,如果我们还没有使用它。

答案 2 :(得分:2)

我很想知道直接比较与阵列检查之间的时间差异。

结论:构建阵列的成本并不是免费的,在考虑速度差异时必须考虑到这一点。

如果在比较时正在构造阵列,则技术上比简单比较慢。因此,简单的比较可以更快地进出循环。

如果数组已经构建,那么在一个大循环中检查数组比进行简单比较要快得多。

$ speed.py
inarray                   x 1000000:  0.277590343844
comparison                x 1000000:  0.347808290754
makearray                 x 1000000:  0.408771123295
import timeit

NUM = 1000000

a = 1
b = 2
c = 3
d = 1

array = {b,c,d}
tup = (b,c,d)
lst = [b,c,d]

def comparison():
    if a == b or a == c or a == d:
        pass

def makearray():
    if a in {b, c, d}:
        pass

def inarray():
    if a in array:
        pass

def maketuple():
    if a in (b,c,d):
        pass

def intuple():
    if a in tup:
        pass

def makelist():
    if a in [b,c,d]:
        pass

def inlist():
    if a in lst:
        pass


def time_all(funcs, params=None):
    timers = []
    for func in funcs:
        if params:
            tx = timeit.Timer(lambda: func(*params))
        else:
            tx = timeit.Timer(lambda: func())
        timers.append([func, tx.timeit(NUM)])

    for func, speed in sorted(timers, key=lambda x: x[1]):
        print "{fn:<25} x {n}: ".format(fn=func.func_name, n=NUM), speed
    print ""
    return

time_all([comparison,
          makearray,
          inarray,
          intuple,
          maketuple,
          inlist,
          makelist
          ], 
         )

这并没有完全回答你的问题,为什么你不经常看到使用的比较。我会猜测,但它可能是1,2,4的组合,以及作者需要的情况写下那段特殊的代码。

我个人根据情况亲自使用这两种方法。选择通常取决于速度或简单性。

编辑:

@ bracco23是对的,使用元组vs阵列vs列表会有一些细微的差别会改变时间。

$ speed.py
inarray                   x 1000000:  0.260784980761
intuple                   x 1000000:  0.288696420718
inlist                    x 1000000:  0.311479982167
maketuple                 x 1000000:  0.356532747578
comparison                x 1000000:  0.360010093964
makearray                 x 1000000:  0.41094386108
makelist                  x 1000000:  0.433603059099