Эффективность оператора Python

Друг (дружелюбный сценарист с низким уровнем навыков для питона) попросил меня просмотреть какой-то код. Я заметил, что у него было 7 отдельных заявлений, которые в основном говорили.

if ( a and b and c): do something 

утверждения a, b, c все проверяли их равенство или отсутствие заданных значений. Когда я посмотрел на него, я обнаружил, что из-за характера тестов я мог бы переписать весь блок логики на две ветви, которые никогда не превышали 3 глубины и редко проходили мимо первого уровня (что делает самый редкий случайный тест первый).

 if a: if b: if c: else: if c: else: if b: if c: else: if c: 

Для меня логически кажется, что он должен быть быстрее, если вы делаете меньше, более простые тесты, которые не работают быстрее и продвигаются дальше. Мои реальные вопросы:

1) Когда я говорю if и else, должен ли быть true, может ли другое проигнорировать полностью?

2) Теоретически

если (a и b и c)

возьмите столько времени, сколько три отдельных заявления if?

8 Solutions collect form web for “Эффективность оператора Python”

if инструкции будут пропускать все в скобке else если она будет равна true. Следует отметить, что беспокоиться об этой проблеме, если она не выполняется миллионы раз за выполнение программы, называется «преждевременной оптимизацией», и ее следует избегать. Если ваш код более четкий с тремя операциями if (a and b and c) , они должны быть оставлены.

Я бы сказал, что один тест проходит так же быстро, как и отдельные тесты. Python также использует так называемую оценку короткого замыкания .

Это означает для (a and b and c) , что b или c больше не будут проверяться, если a является false .

Аналогично, если у вас есть выражение OR (a or b) и a true , b никогда не оценивается.

Итак, чтобы подвести итог, статьи не ускоряются с разделением.

Код:

 import dis def foo(): if ( a and b and c): pass else: pass def bar(): if a: if b: if c: pass print 'foo():' dis.dis(foo) print 'bar():' dis.dis(bar) 

Вывод:

 foo(): 4 0 LOAD_GLOBAL 0 (a) 3 JUMP_IF_FALSE 18 (to 24) 6 POP_TOP 7 LOAD_GLOBAL 1 (b) 10 JUMP_IF_FALSE 11 (to 24) 13 POP_TOP 14 LOAD_GLOBAL 2 (c) 17 JUMP_IF_FALSE 4 (to 24) 20 POP_TOP 5 21 JUMP_FORWARD 1 (to 25) >> 24 POP_TOP 7 >> 25 LOAD_CONST 0 (None) 28 RETURN_VALUE bar(): 10 0 LOAD_GLOBAL 0 (a) 3 JUMP_IF_FALSE 26 (to 32) 6 POP_TOP 11 7 LOAD_GLOBAL 1 (b) 10 JUMP_IF_FALSE 15 (to 28) 13 POP_TOP 12 14 LOAD_GLOBAL 2 (c) 17 JUMP_IF_FALSE 4 (to 24) 20 POP_TOP 13 21 JUMP_ABSOLUTE 29 >> 24 POP_TOP 25 JUMP_ABSOLUTE 33 >> 28 POP_TOP >> 29 JUMP_FORWARD 1 (to 33) >> 32 POP_TOP >> 33 LOAD_CONST 0 (None) 36 RETURN_VALUE 

Таким образом, хотя настройка такая же, очистка для комбинированного выражения выполняется быстрее, поскольку она оставляет только одно значение в стеке.

По крайней мере, в python эффективность является второй по сравнению с читабельностью, а «Flat лучше, чем вложен».

См. «Дзен Питона»

Я сомневаюсь, что вы увидите измеримую разницу, поэтому я бы рекомендовал делать все, что делает код наиболее читаемым.

Если вы обеспокоены тем, что b или c – это функции, которые вызывается вместо переменных, которые оцениваются, то этот код показывает, что короткое замыкание является вашим другом:

 a = False def b(): print "b was called" return True if a and b(): print "this shouldn't happen" else: print "if b was not called, then short-circuiting works" 

печать

 if b was not called, then short-circuiting works 

Но если у вас есть код, который делает это:

 a = call_to_expensive_function_A() b = call_to_expensive_function_B() c = call_to_expensive_function_C() if a and b and c: do something... 

то ваш код по-прежнему вызывает все 3 дорогие функции. Лучше позволить Python быть Python:

 if (call_to_expensive_function_A() and call_to_expensive_function_B() and call_to_expensive_function_C()) do something... 

который будет вызывать только столько дорогих функций, сколько необходимо для определения общего состояния.

редактировать

Вы можете обобщить это, используя all встроенные:

 # note, this is a list of the functions themselves # the functions are *not* called when creating this list funcs = [function_A, function_B, function_C] if all(fn() for fn in funcs): do something 

Теперь, если вам нужно добавить другие функции или изменить их порядок (возможно, function_A занимает очень много времени, и вам будет полезно, если вы будете фильтровать случаи, которые сначала не сбой function_B или function_C ), вы просто обновляете список funcs . all делает короткое замыкание так же, как если бы вы изложили if, как if a and b and c . (Если функции 'or'ed вместе, используйте any встроенный вместо этого.)

if (a and b and c) сбой, если a является ложным, а не проверяет b или c .

Тем не менее, я лично считаю, что вложенные условности легче читать, чем 2 ^ n комбинаций условностей.

В общем, если вы хотите определить, какой способ сделать что-то быстрее, вы можете написать простой тест с использованием timeit .

if (a and b and c) быстрее и лучше, ради оптимизации кода реального программиста и читаемости кода.

  • Производительность стека в языках программирования
  • Низкая производительность чтения на Python
  • Для распаковки элементов
  • Является ли MATLAB быстрее, чем Python?
  • Python, если vs try-except
  • Улучшение производительности функции трассировки лучей
  • Ускорьте программу, которая вычисляет среднее значение соседей в огромном массиве
  • Почему падение скорости увеличивается для генерации 400 000 000 случайных чисел?
  •  
    Interesting Posts for Van-Lav

    Pandas Dataframe AttributeError: объект DataFrame не имеет атрибута 'design_info'

    Что означает … означает в numpy code?

    Как получить доступ к отдельному элементу в кортеже на RDD в pyspark?

    Как установить прокси-серверы вроде этого «user: pass@6.6.6.6: 8043» в FirefoxDriver of Selenium 2?

    Невозможно вычесть значения времени смещения и наименьшего времени

    Параметрированные запросы с помощью psycopg2 / Python DB-API и PostgreSQL

    Как использовать tf.while_loop () в тензорном потоке

    Confused, такие языки, как python, ruby ​​single threaded? в отличие от java? (для веб-приложений)

    Построение графика по времени (Python)

    Добавление заголовков столбцов / столбцов к матрицам Numpy

    Использование urlencode для текста Devanagari

    sqlalchemy общий внешний ключ (например, в django ORM)

    Графика Python Turtle – как мне управлять, когда окно закрывается?

    Программно получить токен доступа для использования API-интерфейса Facebook Graph

    Отступ не работает должным образом в emacs для python

    Python - лучший язык программирования в мире.