【问题标题】:Python - summarize try-except statementPython - 总结 try-except 语句
【发布时间】:2013-04-10 21:57:01
【问题描述】:

我想总结以下代码。它应该做的是检查计算中的变量是否已分配。如果不是,那么结果将为零。因为我有数百个这样的计算,所以我不想重复尝试,除了每个计算。

我该怎么做?

a = 1
b = 2
d = 3
f = 2

try:
    ab = a + b
except:
    ab = 0

try:    
    ac = a - c
except:
    ac = 0

try:    
    bg = b / g
except:
    ac = 0

【问题讨论】:

  • 例外情况是什么?
  • 如果一个变量没有赋值。
  • 我的意思是一种更好的方式来构建代码而不是检查异常,恕我直言,您应该始终知道分配了哪些变量
  • 我并不完全清楚您要在这里做什么,但也许不是允许取消分配某些变量(这是在交互式情况下吗?为什么不分配变量?),您可以将它们设置为float('nan')。然后任何涉及未定义值的计算都将以nan 传播。
  • 更重要的是:这几乎可以肯定是XY problem。请解释你实际上想要做什么,以及为什么你认为你想要这个,我会给你很好的机会,我们可以解释如何解决你的实际问题,从而使明显的异常问题永远不会出现出现。

标签: python except


【解决方案1】:

编写一个函数来执行此操作,使用lambda(单行函数)来推迟对变量的评估,以防其中一个不存在:

def call_with_default(func, default):
    try:
        return func()
    except NameError:   # for names that don't exist
        return default

ab = call_with_default(lambda: a+b, 0)
# etc.

您可能会受益于使用某种数据结构(例如列表或字典)来包含您的值,而不是将它们存储在单个变量中;然后您可以使用循环来完成所有这些计算,而不是单独编写它们。

【讨论】:

  • 我也在考虑你在第二段中提到的内容;元组很适合,至少对于给定的代码。
  • 您的第一个选项有效。但是,对于所有单独的计算,它仍然需要大量编码。您的第二个选项的问题是每次计算都不同(抱歉在我的原始帖子中没有澄清)。
  • @user1738154 使用lambda 可能有解决方案,但我不确定是否有办法找到像在 Lisp 中一样优雅的解决方案。
  • 此外,如果 OP 的异常出现“如果未分配一个变量”,这将无济于事,因为尝试调用 add_default 将引发完全相同的 NameError,在您之前甚至进入函数。
  • @abarnert:说得好,出于某种原因,我认为可能只是其中一些是None。如果您尝试对甚至可能未定义的变量进行计算,那只会加强您应该使用不同数据结构的情况。无论如何,我已经更新了我的函数以使用 lambda。
【解决方案2】:

对于更通用的情况,您可以使用 lambdas(虽然不是太优雅的解决方案):

def lambda_default(func, default, *args):
    try:
        return func(*args)
    except:
        return default

abc = lambda_default(lambda x, y: x + y * z, 0, a, b, c)

如果你有一些常用的函数,你可以再把它们包装成一个def,当然:

def add_default(first, second, default):
    return lambda_default(operator.add, 0, first, second)

ab = add_default(a, b, 0)

【讨论】:

  • 你不需要写lambda x, y: x + y;只需使用operator.add
  • 另外,与 kindall 的回答一样,这对 OP 的实际问题没有帮助。如果未定义 badd_default(a, b, 0) 将引发 NameError,甚至无需调用 add_default
  • @abarnert 谢谢,我已将 operator.add 添加到第二部分,并使第一个更复杂以保持通用性。关于NameError。我认为即使在运行时也无法完全隐藏try-catch。希望我错了。
  • 好吧,关键是您(和所有)添加的内容根本对 OP 没有帮助。他最初的问题是他在使用未定义的变量时得到了NameError,所以他需要在每个表达式中添加try/except 来处理这个问题。使用您提出的解决方案......当使用未定义的变量时,他仍然会得到NameError,因此他仍然需要在每个表达式中添加try/except 来处理它。那么他得到了什么?
  • 同时,当然有一种方法可以在运行时解决这个问题:按名称引用变量,并在globals 中查找它们,正如我的回答所示。这是一个非常糟糕的主意,但这是唯一可以帮助的。
【解决方案3】:

如果您有一堆甚至可能没有定义的变量,那么您可能实际上并没有一堆变量。

例如,如果您尝试构建一个交互式解释器,用户可以在其中创建新变量,请不要尝试将每个用户变量保存为同名的全局变量(如果没有其他原因,除了安全——如果用户试图创建一个名为main 的变量并删除你的main 函数会发生什么?)。存储用户变量字典。

一旦你这样做了,Alexey 和 kindall 建议的解决方案就会起作用:

def add_default(first, second, default):
    try:
        return variables[first] + variables[second]
    except KeyError:
        return default

    variables['ab'] = add_default('a', 'b', 0)

如果您确实需要在同一级别混合您的代码和用户代码,您可以这样做,将globals() 本身用作您的字典:

def add_default(first, second, default):
    try:
        return globals()[first] + globals()[second]
    except KeyError:
        return default

ab = add_default('a', 'b', 0)

但是,以这种方式使用globals 几乎总是表明您之前犯了一个重大设计错误,正确的做法是备份,直到您发现该错误……


同时,来自评论:

我创建了一个所有变量的列表,并在它们是否有赋值时循环遍历它们。如果他们没有,我会将它们设置为 float('nan')。

没有办法创建变量列表(当然,除非通过名称引用它们globals())。您可以创建一个列表,但这对您没有任何好处,因为未定义的变量没有值。

这是另一个迹象,表明您可能需要的不是一堆单独的变量,而是一个字典。

特别是,您可能想要defaultdict

variables = collections.defaultdict(lambda: float('nan'))

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2011-09-29
    • 1970-01-01
    • 1970-01-01
    • 2018-02-24
    • 1970-01-01
    • 2019-06-26
    • 1970-01-01
    • 2011-04-08
    相关资源
    最近更新 更多