Python: оператор try в одной строке
есть ли способ в python превратить try / except в одну строку?
что-то вроде...
b = 'some variable'
a = c | b #try statement goes here
здесь b
является объявленной переменной и c
нет... так что c
выдаст ошибку и a
станет b
...
9 ответов:
нет никакого способа, чтобы сжать
try
/except
блок на одной строке в Python.кроме того, плохо не знать, существует ли переменная в Python, как и в некоторых других динамических языках. Более безопасный способ (и преобладающий стиль) - установить все переменные на что-то. Если они не могут быть установлены, установите их в
None
первый (или0
или''
или что-то, если это более применимо.)
если вы do присвоить все имена, которые вас интересуют в первую очередь, у вас есть варианты.
лучшим вариантом является оператор if.
c = None b = [1, 2] if c is None: a = b else: a = c
однострочный вариант является условным выражением.
c = None b = [1, 2] a = c if c is not None else b
некоторые люди злоупотребляют коротким замыканием поведения
or
для этого. это подвержено ошибкам, поэтому я никогда не использую его.c = None b = [1, 2] a = c or b
рассмотрим следующий дело:
c = [] b = [1, 2] a = c or b
в этом случае
a
наверное должны быть[]
, но это[1, 2]
, потому что[]
имеет значение false в логическом контексте. Поскольку есть много значений, которые могут быть ложными, я не используюor
трюк. (Это та же проблема, с которой сталкиваются люди, когда они говорятif foo:
, когда они имеют в видуif foo is not None:
.)
это ужасно hackish, но я использовал его в приглашении, когда я хотел написать последовательность действий для отладки:
exec "try: some_problematic_thing()\nexcept: problem=sys.exc_info()" print "The problem is %s" % problem[1]
для реальной цели вы пытаетесь выполнить, вы можете попробовать
locals().get('c', b)
; в идеале было бы лучше использовать реальный словарь вместо локального контекста или просто назначить c None перед запуском того, что может или не может его установить.
вы можете сделать это, обратившись к пространству имен dict с помощью
vars()
,locals()
илиglobals()
в зависимости от того является наиболее подходящим для вашей ситуации.>>> b = 'some variable' >>> a = vars().get('c', b)
другой способ-определить контекстный менеджер:
class trialContextManager: def __enter__(self): pass def __exit__(self, *args): return True trial = trialContextManager()
затем использовать
with
оператор для игнорирования ошибок в одной строке:>>> with trial: a = 5 # will be executed normally >>> with trial: a = 1 / 0 # will be not executed and no exception is raised >>> print a 5
в случае ошибки выполнения не будет возникать никаких исключений. Это как
try:
безexcept:
.
Вы упомянули, что используете django. Если это имеет смысл для того, что вы делаете, вы можете использовать:
my_instance, created = MyModel.objects.get_or_create()
created
будет True или False. Может быть, это вам поможет.
parse_float = lambda x, y=exec("def f(s):\n try:\n return float(s)\n except: return None"): f(x)
всегда есть решение.
проблема в том, что его на самом деле модель django.объекты.получить запрос, который я пытаюсь проверить. этот.get возвращает ошибку, если данные не найдены... он не возвращает ни одного (что меня раздражает)
использовать что-то вроде этого:
print("result:", try_or(lambda: model.objects.get(), '<n/a>'))
где try_or-это функция полезности, определенная вами:
def try_or(fn, default): try: return fn() except: return default
дополнительно вы можете ограничить допустимые типы исключений
NameError
,AttributeError
и т. д.
если вам нужно, чтобы на самом деле управлять исключениями:
(изменено из ответа poke53280)>>> def try_or(fn, exceptions: dict = {}): try: return fn() except Exception as ei: for e in ei.__class__.__mro__[:-1]: if e in exceptions: return exceptions[e]() else: raise >>> def context(): return 1 + None >>> try_or( context, {TypeError: lambda: print('TypeError exception')} ) TypeError exception >>>
обратите внимание, что если исключение не поддерживается, оно будет расти, как ожидалось:
>>> try_or( context, {ValueError: lambda: print('ValueError exception')} ) Traceback (most recent call last): File "<pyshell#57>", line 1, in <module> try_or( context, {ValueError: lambda: print('ValueError exception')} ) File "<pyshell#38>", line 3, in try_or return fn() File "<pyshell#56>", line 2, in context return 1 + None TypeError: unsupported operand type(s) for +: 'int' and 'NoneType' >>>
и если
Exception
дается, он будет соответствовать что-нибудь ниже.
(BaseException
выше, поэтому он не будет соответствовать)>>> try_or( context, {Exception: lambda: print('exception')} ) exception
в python3 вы можете использовать contextlib.подавить:
from contextlib import suppress d = {} with suppress(KeyError): d['foo']