Есть ли способ в python превратить try / except в одну строку?
что-то типа...
b = 'some variable'
a = c | b #try statement goes here
Где b
объявленная переменная, а c
не ... поэтому c
выдаст ошибку и a
станет b
...
Ответы:
В Python нет способа сжать блок try
/ except
в одну строку.
Кроме того, плохо не знать, существует ли переменная в Python, как и в некоторых других динамических языках. Более безопасный способ (и преобладающий стиль) - установить все переменные на что-то. Если они не могут быть настроены, установите их в None
первую очередь ( 0
или ''
или что-то еще, если это более применимо).
Если вы делаете правопреемником все имена , которые вы заинтересованы в первых, у вас есть варианты.
Лучшим вариантом является оператор 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]
потому, что []
в логическом контексте ложно. Поскольку существует множество значений, которые могут быть ложными, я не использую этот or
трюк. (Это та же проблема, с которой сталкиваются люди, когда говорят, if foo:
когда имеют в виду if foo is not None:
.)
try
/ except
block не существует однострочного синтаксиса . К счастью, линии дешевы, поэтому решение из 4 строк должно вам подойти. ;-)
get
если не хотите исключений. filter
Вместо этого используйте .
Это ужасно хакерски, но я использовал его в командной строке, когда хотел написать последовательность действий для отладки:
exec "try: some_problematic_thing()\nexcept: problem=sys.exc_info()"
print "The problem is %s" % problem[1]
По большей части меня совсем не беспокоит ограничение no-single-line-try-except, но когда я просто экспериментирую и хочу, чтобы readline вызывала сразу весь фрагмент кода в интерактивном интерпретаторе, поэтому что я могу как-то это отрегулировать, этот маленький трюк пригодится.
Для реальной цели, которую вы пытаетесь достичь, вы можете попробовать locals().get('c', b)
; в идеале было бы лучше использовать реальный словарь вместо локального контекста или просто присвоить c параметру None перед запуском того, что может или не может быть установлено.
problem[0]
вернуть то , что функция возвращает?
В python3 вы можете использовать contextlib.suppress :
from contextlib import suppress
d = {}
with suppress(KeyError): d['foo']
Другой способ - определить диспетчер контекста:
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:
.
Версия ответа poke53280 с ограниченными ожидаемыми исключениями.
def try_or(func, default=None, expected_exc=(Exception,)):
try:
return func()
except expected_exc:
return default
и его можно было бы использовать как
In [2]: try_or(lambda: 1/2, default=float('nan'))
Out[2]: 0.5
In [3]: try_or(lambda: 1/0, default=float('nan'), expected_exc=(ArithmeticError,))
Out[3]: nan
In [4]: try_or(lambda: "1"/0, default=float('nan'), expected_exc=(ArithmeticError,))
---------------------------------------------------------------------------
TypeError Traceback (most recent call last)
[your traceback here]
TypeError: unsupported operand type(s) for /: 'str' and 'int'
In [5]: try_or(lambda: "1"/0, default=float('nan'), expected_exc=(ArithmeticError, TypeError))
Out[5]: nan
parse_float = lambda x, y=exec("def f(s):\n try:\n return float(s)\n except: return None"): f(x)
Всегда есть решение.
Проблема в том, что на самом деле это запрос django model.objects.get, который я пытаюсь проверить. .get возвращает ошибку, если данные не найдены ... он не возвращает None (что меня раздражает)
Используйте что-то вроде этого:
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
и т. Д.
Вы можете сделать это путем доступа к пространству имен Dict с использованием vars()
, locals()
или globals()
, в зависимости от того является наиболее подходящей для вашей ситуации.
>>> b = 'some variable'
>>> a = vars().get('c', b)
Как насчет использования двух строк. Это нормально ?
>>> try: a = 3; b= 0; c = a / b
... except : print('not possible'); print('zero division error')
...
not possible
zero division error
если вам действительно нужно управлять исключениями:
(изменено из ответа 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, вдохновленный Вальтером Мундтом
exec("try:some_problematic_thing()\nexcept:pass")
Для нескольких строк в одну строку
exec("try:\n\tprint('FirstLineOk')\n\tsome_problematic_thing()\n\tprint('ThirdLineNotTriggerd')\nexcept:pass")
Ps: Exec небезопасно использовать с данными, которые вы не контролируете.