В Python я часто слышу, что лучше «просить прощения» (перехват исключений), а не «спрашивать разрешение» (проверка типа / условия). Что касается принудительного набора утки в Python, это
try:
x = foo.bar
except AttributeError:
pass
else:
do(x)
лучше или хуже чем
if hasattr(foo, "bar"):
do(foo.bar)
else:
pass
с точки зрения производительности, читабельности, «питона» или какого-то другого важного фактора?
exceptions
python
duck-typing
darkfeline
источник
источник
hasattr
он реализован именно с этой попытки. Не уверен, если это правда ... (это будет действовать по-другому на свойства, не так ли? Может быть, я думаю оgetattr
..)hasattr
действительно использует эквивалент C-APIgetattr
(возврат вTrue
случае успеха,False
если нет), но обработка исключений в C происходит намного быстрее.Ответы:
Это действительно зависит от того, как часто вы думаете, что будет выдано исключение.
Оба подхода, на мой взгляд, одинаково верны, по крайней мере, с точки зрения читабельности и питонности. Но если 90% ваших объектов не имеют атрибута,
bar
вы заметите явную разницу в производительности между двумя подходами:Но если 90% ваших объектов действительно имеют атрибут, таблицы были повернуты:
Таким образом, с точки зрения производительности, вы должны выбрать подход, который лучше всего подходит для ваших обстоятельств.
В конце концов, какое-то стратегическое использование
timeit
модуля может оказаться самой питонской вещью, которую вы можете сделать.источник
hasattr
, он на самом деле делает C-api эквивалентом try-исключений, в любом случае, так как оказывается, что единственный общий способ определить, есть ли у объекта атрибут в Python, - попытаться получить к нему доступ.В Python вы часто получаете лучшую производительность, выполняя действия Python. В других языках использование исключений для управления потоком, как правило, рассматривается как ужасная идея, поскольку исключения обычно накладывают чрезвычайные накладные расходы. Но поскольку этот метод явно одобрен в Python, интерпретатор оптимизирован для этого типа кода.
Как и во всех вопросах производительности, единственный способ убедиться в этом - профилировать ваш код. Напишите обе версии и посмотрите, какая из них работает быстрее. Хотя, по моему опыту, «путь Python», как правило, самый быстрый путь.
источник
Производительность, я чувствую, является второстепенной проблемой. Если это произойдет, профилировщик поможет вам сосредоточиться на реальных узких местах, которые могут или не могут быть, как вы относитесь к возможным незаконным аргументам.
С другой стороны, удобочитаемость и простота всегда являются главной заботой. Здесь нет жестких правил, просто используйте свое суждение.
Это универсальный вопрос, но актуальны соглашения, касающиеся окружающей среды или языка. Например, в Python обычно нормально использовать ожидаемый атрибут и позволить возможному AttributeError достигнуть вызывающей стороны.
источник
С точки зрения корректности , я думаю, что обработка исключений - это правильный путь (хотя иногда я сам использую подход hasattr ()). Основная проблема, связанная с использованием функции hasattr (), заключается в том, что она превращает нарушения кодовых контрактов в скрытые сбои (это большая проблема в JavaScript, который не создает несуществующие свойства).
источник