Python: try-except как выражение?
Я снова и снова сталкиваюсь с подобным узором:
variable = ""
try:
variable = ... do some file loading stuff ...
except:
variable = ""
Есть ли способ сконденсировать это в одно выражение? Как и с операторами if-else, вы можете повернуть:
variable = ""
if something:
variable = somethingelse
else:
variable = ""
в
variable = somethingelse if something else ""
Есть ли эквивалентная вещь для try-catch?
Ответы
Ответ 1
Так как agf уже предоставил подход, который я бы рекомендовал, вот версия его подпрограммы с несколькими незначительными улучшениями:
def try_except(success, failure, *exceptions):
try:
return success()
except exceptions or Exception:
return failure() if callable(failure) else failure
Эта версия:
-
Позволяет указать, какие именно исключения будут уловлены в качестве дополнительных необязательных аргументов. Вы всегда должны улавливать минимальный набор исключений, которые будут выполнять задание, и позволяют исключениям, с которыми вы не можете обрабатывать пузырь до вызывающего.
-
Поддерживает использование простого значения, а также функцию для значения отказа. Это избавит вас от необходимости использовать лямбда во многих случаях. (Конечно, вместо lambda: ''
вы можете просто использовать str
.)
Ответ 2
def try_except(success, failure):
try:
return success()
except:
return failure()
variable = try_except(do_some_file_loading_stuff, lambda: '')
Я думаю, что код сам объясняет. Он возвращает значение, возвращаемое success
, если нет ошибки, затем возвращается значение, возвращаемое failure
. Если do_some_file_loading_stuff
является выражением, а не просто вызовом функции, оберните его также в lambda
.
Изменить: @kindall, и я немного улучшил его версию, так что он так же быстро, как и мой, можно назвать точно так же, если вы хотите, имеет больше возможностей и имеет такое же количество строк, Используйте его!
def try_except(success, failure, *exceptions):
try:
return success()
except exceptions or Exception:
return failure() if callable(failure) else failure
Ответ 3
Вот менеджер контекста, который предоставляет немного ярлыка:
from contextlib import contextmanager
@contextmanager
def catch(*exceptions, **kwargs):
try:
yield kwargs.get("default", None)
except exceptions or Exception:
pass
Использование:
with catch(ZeroDivisionError, default=0) as x:
x = 3 / 0 # error
print x # prints 0, the default
Основная идея здесь заключается в том, что диспетчер контекста возвращает все значения по умолчанию, которые вы передаете ему, которое затем назначается переменной, указанной в предложении with
statement as
. Затем внутри контекста вы выполняете оператор, который пытается назначить эту же переменную. Если он вызывает исключение, менеджер контекста ловит и молча игнорирует его, но поскольку присваивание не произошло, значение по умолчанию остается.
Может быть особенно полезно для многолинейных вычислений, которые, тем не менее, приводят к одному значению.
Ответ 4
К сожалению, нет, для него нет языковой конструкции, и я тоже не знаю какой-либо четкой и лаконичной идиомы. Я всегда хотел чего-то подобного. Некоторое время назад кто-то дал мне основания для того, чтобы Python не имел что-то вроде variable = function_cal() except ""
, но они были не очень убедительными, и я все еще пропускаю эту конструкцию языка:)
Ответ 5
Очевидно, что последний способ сделать это более кратким и предпочитается многими программистами, такими как вы.
В то время как сам язык не предоставляет "однострочный try-except-catch" по каким-либо причинам, все хорошее и необходимое, я полагаю, вы можете в целом выполнить это, немного изменив программу; например, например:
try:
a_var = a_dict.get('abcd')
except a_dict.KeyError:
a_var = ''
в
a_var = a_dict.get('abcd',default='')
и аналогично для запросов БД;
try:
a_qs = Model.objects.get(id=42)
except Model.DoesNotExist:
a_qs = Model.objects.create(id=42)
с
a_qs = Model.objects.get_or_create(id=42,**kwargs)
и добавьте аналогичный API в свои собственные программы, где это возможно. try-except довольно "дешево" в Python, и программирование на основе исключения предпочтительнее, чем подход "check-first", обычно предлагаемый на Java, например, языки из-за дорогостоящего характера обработки исключений. Таким образом, вы должны скорее обернуть эту "захватывающую вещь" в методе/функции и вызвать ее где угодно, например, в случае с dict и другими конструкциями.
Ответ 6
Нет простого способа упростить оператор try/catch, такой как пример if/else, но я хочу указать, что оператор python с инструкцией, представленный в python2.5, сделал много интерфейсов для файла /db io try упрощения и исключения исключений. Операции ввода-вывода, как правило, используются там, где используется множество операторов try/catch.
with open("myfile.txt", "r") as f:
# Do stuff with f
вместо
try:
f = open("myfile.txt", "r")
# Do stuff with f
except:
pass
finally:
if f: f.close