Подтвердить что ты не робот

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?

4b9b3361

Ответ 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