Ответ 1
Компактный способ записи этой функции - использовать any
и выражение генератора:
def validate(val):
conditions = (cond1, cond2, cond3)
return not any(cond(val) for cond in conditions)
Функции any
и all
работают в коротком замыкании, поэтому они прекращают тестирование, как только они имеют определенный результат, т.е. any
останавливается, как только он достигает значения True-ish, all
останавливается, как только он достигает значения False-ish, поэтому эта форма тестирования достаточно эффективна.
Я также должен отметить, что гораздо эффективнее передать выражение генератора, подобное этому, в all
/any
, чем понимание списка. Поскольку all
/any
прекратить тестирование, как только они получат правильный результат, если вы их подаете из генератора, тогда генератор тоже остановится, поэтому в приведенном выше коде, если cond(val)
оценивает значение True-ish no будут проверены дополнительные условия. Но если вы передадите all
/any
понимание списка, например any([cond(val) for cond in conditions])
, весь список должен быть создан до того, как all
/any
может даже начать тестирование.
Вы не указали нам внутреннюю структуру ваших функций cond
, но вы упомянули assert
в своем вопросе, поэтому я чувствую, что здесь следующие замечания.
Как я уже упоминал в комментариях, assert
не должен использоваться для проверки данных, он используется для проверки логики программы. (Кроме того, управление утверждениями можно отключить с помощью опции командной строки -O). Правильное исключение для использования с данными с недопустимыми значениями - ValueError
, а для объектов, которые являются неправильным типом, используйте TypeError
. Но имейте в виду, что исключения предназначены для обработки ситуаций, которые являются исключительными.
Если вы ожидаете много искаженных данных, тогда, как правило, более эффективно использовать логику на основе if
, чем исключения. Обработка исключений Python довольно быстро, если исключение фактически не создано, на самом деле оно быстрее, чем эквивалентный код на основе if
. Однако, если возникло исключение, говорят, что более 5-10% времени, то код try...except
будет заметно медленнее, чем эквивалент if
.
Конечно, иногда использование исключений - единственный разумный вариант, хотя ситуация не является настолько исключительной. Классическим примером является преобразование коллекции числовых строк в реальные числовые объекты, так что строки, представляющие целые числа, преобразуются в целые объекты, другие числовые строки преобразуются в поплавки, а другие строки остаются в виде строк. Стандартный способ сделать это в Python включает использование исключений. Например:
def convert(s):
''' Convert s to int or float, if possible '''
try:
return int(s)
except ValueError:
try:
return float(s)
except ValueError:
return s
data = ['42', 'spam', '2.99792458E8']
out = [convert(u) for u in data]
print(out)
print([type(u) for u in out])
Выход
[42, 'spam', 299792458.0]
[<class 'int'>, <class 'str'>, <class 'float'>]
Используя "Посмотрите, прежде чем прыгать" здесь возможно, но это делает код более сложным, потому что вам нужно иметь дело с возможным минусом знаков и научных обозначений.