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

Python: оператор try в одной строке

Есть ли способ в python включить try/except в одну строку?

что-то вроде...

b = 'some variable'
a = c | b #try statement goes here

Где b - объявленная переменная, а c - не... поэтому c выдаст ошибку, а a станет b...

4b9b3361

Ответ 1

Невозможно сжать блок try/except на одну строку в Python.

Кроме того, плохо знать, существует ли переменная в 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:.)

Ответ 2

Это ужасно хакерский, но я использовал его в приглашении, когда хотел написать последовательность действий для отладки:

exec "try: some_problematic_thing()\nexcept: problem=sys.exc_info()"
print "The problem is %s" % problem[1]

По большей части меня совсем не беспокоит ограничение не-одиночной строки-try-except, но когда я просто экспериментирую, и я хочу, чтобы readline сразу вызывал целый фрагмент кода в интерактивный интерпретатор, чтобы как можно скорее его настроить, этот небольшой трюк пригодится.

Для фактической цели, которую вы пытаетесь выполнить, вы можете попробовать locals().get('c', b); в идеале было бы лучше использовать настоящий словарь вместо локального контекста или просто назначить c None, прежде чем запускать все, что может или не может его установить.

Ответ 3

Другим способом является определение менеджера контекста:

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:.

Ответ 4

parse_float = lambda x, y=exec("def f(s):\n try:\n  return float(s)\n except:  return None"): f(x)

Всегда есть решение.

Ответ 5

Вы можете сделать это, обратившись к пространству имен dict, используя vars(), locals() или globals(), в зависимости от того, что наиболее подходит для вашей ситуации.

>>> b = 'some variable'
>>> a = vars().get('c', b)

Ответ 6

Вы упомянули, что используете джанго. Если это имеет смысл для того, что вы делаете, вы можете использовать:

my_instance, created = MyModel.objects.get_or_create()

created будет True или False. Возможно, это поможет вам.

Ответ 7

Проблема в том, что на самом деле это запрос 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 и т.д.

Ответ 8

В python3 вы можете использовать contextlib.suppress:

from contextlib import suppress

d = {}
with suppress(KeyError): d['foo']

Ответ 9

если вам нужно управлять исключениями:
(модифицировано из ответа 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

Ответ 10

Версия ответа 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