在 Pythonese 中怎么说 - 做某事除非它导致错误(不求助于多级 try/execpt 块)

How to say in Pythonese - do something unless it causes an error (without resorting to multilevel try/execpt blocks)

这有点难以解释,所以希望我能连贯地表达问题:

假设我有这个列表:

my_list = ["a string", 45, 0.5]

要了解问题的关键点是 my_list 是由另一个函数生成的;我事先不知道有关 my_list 的任何信息,特别是它的长度和它的任何成员的数据类型。

接下来说每次生成<my_list>,都有一些我要对它进行的预定操作。例如,我想:

my_text = my_list[1]+"hello"
some_var = my_list[10]
mini_list = my_list[0].split('s')[1]
my_sum = my_list[7]+2

等这里重要的一点是,它是大量的操作。

显然,其中一些操作会在任何给定的 my_list 下成功,而有些会失败,重要的是,那些失败的操作将以不可预测的 Error 类型进行;但我需要 运行 在每一代 my_list.

上全部

一个明显的解决方案是对每个操作使用 try/except:

try:
  my_text = my_list[1]+"hello"
except:    
  my_text = "None"

try:
  some_var = my_list[10]
except:
  some_var = "couldn't do it"

等等

但是操作量大的话,会很麻烦。我调查了关于多个 try/except 的各种问题,但除非我遗漏了什么,否则他们不会解决这个问题。

根据某人的建议(抱歉,丢失了 link),我尝试创建一个内置函数 try/except,创建另一个这些操作的列表,并将每个操作发送到功能。类似于

def careful(op):
  try:
    return op
  else:
    return "None"

并将其与第一个操作一起使用:

my_text = careful(my_list[1]+"hello")

问题是 python 似乎评估 careful() 参数 之前 它被发送到函数并且在它被捕获之前生成错误...

所以我想我正在寻找一种可以执行类似操作的三元运算符形式:

my text = my_list[1]+"hello" if (this doesn't cause any type of error) else "None"

但是,即使存在,我也找不到...

任何想法都将受到欢迎,对于冗长的post感到抱歉。

也许是这样的?

def careful(op, default):
  ret = default
  try:
    ret = computation()
  else:
    pass
  return ret

这听起来像 XY Problem

如果您可以更改源逻辑,返回 dict 可能是更好的解决方案。然后您可以在执行某些操作之前确定键是否存在,并且还可以查找如果键存在于另一个 dict.

中应该执行的操作

如果您必须这样做,请考虑将操作集合保存为字符串并在循环中对它们调用exec

actions = [
    'my_text   = my_list[1]+"hello"',
    'some_var  = my_list[10]',
    'mini_list = my_list[0].split("s")[1]',
    'my_sum    = my_list[7]+2',
]

如果您将此合集设置为 dict,您还可以指定一个默认值

请注意,如果默认操作(或操作字符串的一部分)是字符串,则必须将其引用两次。如果您已经进行了复杂的转义,请考虑为此使用块引号,例如返回原始字符串或表示正则表达式的字符串

{
    "foo = bar": r"""r'[\w]+baz.*'"""
}

完整示例:

>>> actions_defaults = {
...     'my_text   = my_list[1]+"hello"':       '"None"',
...     'some_var  = my_list[10]':              '"couldn\'t do it"',
...     'mini_list = my_list[0].split("s")[1]': '"None"',
...     'my_sum    = my_list[7]+2':             '"None"',
... }
>>>
>>> for action, default in actions_defaults.items():
...     try:
...         exec(action)
...     except Exception:  # consider logging error
...         exec("{} = {}".format(action.split("=")[0], default))
...
>>> my_text
'None'
>>> some_var
"couldn't do it"

其他说明

  • 这很邪恶
  • 在 运行 之前声明你的变量是它们的默认值可能是 better/clearer (足以 except 块中的 pass,因为分配将失败)
  • 您可能 运行 进入奇怪的范围并且需要通过 locals()
  • 访问一些变量