除了在一行中,我应该如何放入 try/?

在 python 中有没有一种方法可以将 try/but 转换为单行?

比如..。

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

其中 b是一个声明的变量,而 c不是... 因此 c将抛出一个错误,而 a将成为 b..。

136479 次浏览

在 Python 中,无法将 try/except块压缩到一行。

此外,不知道变量是否存在于 Python 中是一件坏事,就像在其他动态语言中一样。更安全的方法(以及流行的风格)是将所有变量设置为某个值。如果它们可能没有被设置,那么首先将它们设置为 None(或者 0或者 ''或者其他更适用的设置)


如果你的 分配所有的名称,你感兴趣的第一,你有选择。

  • 最好的选择是 if 语句。

    c = None
    b = [1, 2]
    
    
    if c is None:
    a = b
    else:
    a = c
    
  • The one-liner option is a conditional expression.

    c = None
    b = [1, 2]
    a = c if c is not None else b
    
  • Some people abuse the short-circuiting behavior of or to do this. This is error prone, so I never use it.

    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:时,也会遇到同样的问题。)

你提到你正在使用 django。如果它对你正在做的事情有意义,你可能想要使用:

my_instance, created = MyModel.objects.get_or_create()

created将是真或假。也许这将帮助你。

您可以通过使用 vars()locals()globals()访问名称空间 dict 来实现,以最适合您的情况为准。

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

这是非常骇人听闻的,但是当我想编写一系列调试操作时,我曾在提示符下使用过它:

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

在大多数情况下,除了限制之外,我一点也不在乎不能单行尝试,但是当我在实验时,我想让 readline 在交互式解释器中一次回想起一整块代码,这样我就可以以某种方式调整它,这个小技巧就派上用场了。

对于您试图实现的实际目的,您可以尝试 locals().get('c', b); 理想情况下,最好使用一个真正的字典而不是本地上下文,或者在运行任何可能或可能不设置的设置之前将 c 赋值给 Nothing。

另一种方法是定义上下文管理器:

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

在运行时错误的情况下不会引发任何异常,就像没有 except:try:一样。

问题在于,它实际上是一个我正试图测试的 django model. objects.get 查询。的。如果没有找到数据,get 返回一个错误... ... 它不返回 Nothing (这让我很恼火)

使用这样的东西:

print("result:", try_or(lambda: model.objects.get(), '<n/a>'))

其中 try _ or 是由您定义的实用函数:

def try_or(fn, default):
try:
return fn()
except:
return default

可以选择将接受的异常类型限制为 NameErrorAttributeError等。

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

总会有办法的。

如果需要实际管理异常:
(修改自 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中,你可以使用 抑制:

from contextlib import suppress


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

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

灵感来自 Walter Mundt 的 Python 3

exec("try:some_problematic_thing()\nexcept:pass")

将多个行转换为一行

exec("try:\n\tprint('FirstLineOk')\n\tsome_problematic_thing()\n\tprint('ThirdLineNotTriggerd')\nexcept:pass")

附注: 对于无法控制的数据,使用 Exec 是不安全的。

用两条线怎么样,可以吗?

>>> try: a = 3; b= 0; c = a / b
... except : print('not possible'); print('zero division error')
...
not possible
zero division error

下面是@surendra _ ben 提供的答案的一个简单版本

a = "apple"
​
try: a.something_that_definitely_doesnt_exist
except: print("nope")


...


nope

在一行中使用 with语法:

class OK(): __init__ = lambda self, *isok: setattr(self, 'isok', isok); __enter__ = lambda self: None; __exit__ = lambda self, exc_type, exc_value, traceback: (True if not self.isok or issubclass(exc_type, self.isok) else None) if exc_type else None

忽略任何错误:

with OK(): 1/0

忽略指定的错误:

with OK(ZeroDivisionError, NameError): 1/0

双线程版本对我不起作用。我在 ubuntu 20.04 x64上使用 VSCode。它只有在我将异常语句移动到一个新行时才能工作。该尝试可以保持为单行。所以我至少需要3行。不知道这是一个 bug 还是一个特性。

一个实际的干净的单行线程器读起来(有点)像 try-but 块,并且不是超级脏的,如下所示:

val = (lambda: dictionary["wrong key"]) % cept(KeyError) % (lambda: "default value")

这里需要这样的装置

from infix import mod_infix


def cept(*args, as_exc=False):
if not args:
args = Exception


@mod_infix
def _cept(f1, f2):
try:
return f1()
except args as e:
if as_exc:
return f2(e)
else:
return f2()
return _cept

我希望我可以除掉 Lambda 但是没有办法。

我个人认为 https://peps.python.org/pep-0463/的拒绝通知不能令人满意。贵都,如果你正在读这(是的,我希望) ,请让我们知道。

我在这里看到了使用 try 的多个示例。.除了处理字典键。在这些情况下,适当的方法是使用 .get方法,当 None不可用时它将返回 None。例子

my_dict = {'a': 1, 'b': 2}
print(my_dict.get('c'))
# Output: None