2014-01-09 2 views
1

я читал какой-то код, и я заметил, что этот код имеет многие из этих линий:операция сравнения Python, если и None

try: 
    rv = somefunction() 
except SomeException, e: 
    rv = 0 

if rv == 0: 
    doSomething() ... 

Это мне показалось, что с использованием этого стиля операций сравнения обязано быть медленнее чем:

try: 
    rv = somefunction() 
except SomeException, e: 
    rv = None 

if is not None: 
    doSomething() 
    ... 
+0

Как @zybjtu просто указал на мой ответ, если 'doSomething()' следует вызывать, если 'somefunction()' возвращает '0', ваши предложенные изменения нарушают код. – jonrsharpe

+0

@MartijnPieters, как обычно: острые глаза! исправлено. – Oz123

+2

Скажите, что '== 0' стоит 5 центов,' is None' стоит 2 цента, а 'except' стоит 1000 долларов. $ 1000.02 действительно дешевле, чем $ 1000,05? – georg

ответ

1

Возможно, это зависит от того, находитесь ли вы в python 2 или python 3. В python 2 единственной «медленной» операцией является «== None». Я думал, что это потому, что целые числа в низких диапазонах были запроектированными объектами, но на самом деле это не имело значения.

In [53]: x = 0 

In [54]: %timeit x is 0 
10000000 loops, best of 3: 38 ns per loop 

In [55]: %timeit x == 0 
10000000 loops, best of 3: 36.5 ns per loop 

In [56]: x = 1 

In [57]: %timeit x is 0 
10000000 loops, best of 3: 37.3 ns per loop 

In [58]: %timeit x == 0 
10000000 loops, best of 3: 36.5 ns per loop 

In [59]: %timeit x is None 
10000000 loops, best of 3: 38.1 ns per loop 

In [60]: %timeit x == None 
10000000 loops, best of 3: 82.9 ns per loop 

Теперь, в первых 3-х случаях, х является INT, который имеет тот же тип в первых 3-х случаях, а не в последнюю очередь. Так попробовал еще одну вещь, что делает ха строку, поэтому она не будет соответствовать типу с 0:

In [62]: x = 'x' 

In [63]: %timeit x is 0 
10000000 loops, best of 3: 38.7 ns per loop 

In [64]: %timeit x == 0 
10000000 loops, best of 3: 92.5 ns per loop 

In [65]: %timeit x is None 
10000000 loops, best of 3: 39.1 ns per loop 

In [66]: %timeit x == None 
10000000 loops, best of 3: 77.1 ns per loop 

В этом случае, «не» по-прежнему довольно быстро, независимо от того, какие типы, при проверке смешанного типа равенства медленнее. Это имеет смысл, так как «is» - это просто проверка равенства на id, тогда как equals могут быть произвольно медленными.

Это означает, что если вы действительно беспокоитесь об этом (вам, вероятно, не нужно упоминаться, если это не указано во внутреннем цикле), вы должны создать объект-дозор (в любое время), а затем использовать is, чтобы проверить его непосредственно. None является удобным, если он не является допустимым значением; 0 или -1 могут выполнять ту же роль. Но это не обязательно.

0

Чтобы показать свою половинку, это, возможно, правда, я сделал некоторые бенчмаркинг с None, 0 и False:

Я прочитал до этого вопроса, When is the `==` operator not equivalent to the `is` operator? (Python). И я даже добавил некоторые бенчмаркинг, чтобы попытаться убедить своих товарищей, что это может быть оптимизировано:

In [92]: def TestInt(): 
    ....:  i = 0 
    ....:  if i: 
    ....:   pass 
    ....:  

In [93]: def TestBool(): 
    ....:  i = False 
    ....:  if i: 
    ....:   pass 
    ....:  

In [95]: def TestNone(): 
    ....:  i = None 
    ....:  if i: 
    ....:   pass 
    ....:  


In [97]: timeit.timeit(TestInt, number=10**5) 
Out[97]: 0.01352691650390625 

In [98]: timeit.timeit(TestBool, number=10**5) 
Out[98]: 0.014671087265014648 

In [99]: timeit.timeit(TestNone, number=10**5) 
Out[99]: 0.009851932525634766 

Очевидно сравнение, если объект не None всегда немного быстрее!

+0

Те испытания бессмысленны. Обратите внимание, что 'if i' не совпадает с' if i == 0', равно как и 'if i is not None'. Все испускают тонко отличающийся код, который может полностью изменить результаты теста. –

+0

действительно ли это стоит? – zhangxaochen

+2

Да, тестирование для 'None' происходит быстрее, потому что Python может сделать его постоянным, безопасным в знании, что' None = 0' не разрешено. В Python 3 'True' и' False' теперь являются ключевыми словами, и то же самое относится к тем. –

2

было бы более эффективным, чтобы просто сделать:

try: 
    rv = somefunction() 
except SomeException, e: 
    doSomething() ... 

Вы можете по-прежнему необходимо установить rv = 0 если целое значение нужно в другом месте, что является ограничивающим фактором на ваших примерах выше.

+0

Я не уверен, что вы правы, может быть somefunction() может вернуть нулевое значение, тогда он хочет вызвать doSomething() – YaleCheung

+0

А, да; вы правы, спасибо. Но в этом случае другие предложенные варианты не будут работать в любом случае! – jonrsharpe

Смежные вопросы