У меня есть оператор in if-elif-elif-else, в котором в 99% случаев выполняется оператор else:
if something == 'this':
doThis()
elif something == 'that':
doThat()
elif something == 'there':
doThere()
else:
doThisMostOfTheTime()
Эта конструкция выполняется много раз , но поскольку она перебирает все условия, прежде чем попадет в else, я чувствую, что это не очень эффективно, не говоря уже о Pythonic. С другой стороны, ему действительно нужно знать, выполняется ли какое-либо из этих условий, поэтому он все равно должен его протестировать.
Кто-нибудь знает, можно ли и как это сделать более эффективно, или это просто лучший способ сделать это?
python
performance
if-statement
kramer65
источник
источник
sort
те вещи, на которых работает ваша цепочка if / else ..., чтобы все элементы, которым соответствует одно из условий, находились на одном конце, а все остальные - на другом? Если это так, вы можете увидеть, быстрее / элегантнее это или нет. Но помните, если нет проблем с производительностью, об оптимизации волноваться рано.if not something.startswith("th"): doThisMostOfTheTime()
еще одно сравнение вelse
предложении.something
или аналогичные сравнения выполняются несколько раз для одного и того же значения?Ответы:
Код...
... похоже, что он должен быть быстрее, но на самом деле он медленнее, чем конструкция
if
...elif
...else
, потому что он должен вызывать функцию, что может привести к значительным накладным расходам производительности в узком цикле.Рассмотрим эти примеры ...
1.py
2.py
3.py
4.py
... и обратите внимание на количество процессорного времени, которое они используют ...
... используя время пользователя из
time(1)
.Вариант № 4 требует дополнительных затрат памяти на добавление нового элемента для каждого отдельного пропуска ключа, поэтому, если вы ожидаете неограниченное количество отдельных пропущенных клавиш, я бы выбрал вариант № 3, который по-прежнему является значительным улучшением. оригинальная конструкция.
источник
dict
медленнее, но тогда ваши тайминги фактически показывают, что это второй самый быстрый вариант.dict.get()
это медленнее, а это2.py
- самый медленный из всех.Я бы создал словарь:
Теперь используйте только:
Если
something
не найден вoptions
dict, тоdict.get
вернет значение по умолчаниюdoThisMostOfTheTime
Некоторые сравнения по времени:
Сценарий:
Полученные результаты:
Для
10**5
несуществующих ключей и 100 действительных ключей:Итак, для обычного словаря проверка ключа здесь
key in options
является наиболее эффективным способом:источник
options = collections.defaultdict(lambda: doThisMostOfTheTime, {'this': doThis,'that' :doThat, 'there':doThere}); options[something]()
немного более эффективен.options
dict, чтобы избежать его перестройки, тем самым перемещая часть (но не всю) логики подальше от точки использования. Тем не менее, хороший трюк!try: options[key]() except KeyError: doSomeThingElse()
(так какif key in options: options[key]()
вы дважды ищете в словареkey
Умеете ли вы использовать pypy?
Сохранение исходного кода, но запуск его на pypy дает мне 50-кратное ускорение.
CPython:
Pypy:
источник
Вот пример оператора if с динамическими условиями, переведенными в словарь.
Это способ, но, возможно, не самый питонический способ сделать это, потому что он менее читабелен для тех, кто не владеет Python.
источник
Люди предупреждают об этом
exec
из соображений безопасности, но это идеальный случай для этого.Это простой конечный автомат.
источник