基本Python:异常抛出与局部变量作用域/绑定

4 投票
4 回答
7035 浏览
提问于 2025-04-15 22:12

我有一个关于Python的基本“最佳实践”的问题。我看到已经有一些与这个问题相关的StackOverflow回答,但它们都涉及复杂的例子或者多个因素,让人看得很困惑。

给定这段代码:

#!/usr/bin/python

def test_function():
   try:
      a = str(5)
      raise
      b = str(6)
   except:
      print b

test_function()

有什么好的方法可以避免在异常处理器中出现“UnboundLocalError: local variable 'b' referenced before assignment”的错误呢?

Python有没有简单优雅的方式来处理这个问题?如果没有,那有没有什么不那么优雅的方法?在一个复杂的函数中,我希望能避免在打印调试信息之前,检查每个局部变量是否存在。

4 个回答

2

你可以使用一个内置的方法 locals() 来检查变量是否在本地范围内被定义。

http://docs.python.org/library/functions.html#locals

#!/usr/bin/python

def test_function():
  try:
      a = str(5)
      raise
      b = str(6)
  except:
      if 'b' in locals(): print b

test_function()
6

你可以在尝试块外面初始化你的变量。

a = None
b = None       
try:
    a = str(5)
    raise
    b = str(6)
except:
    print b
10

Python有没有优雅的方法来处理这个问题?

为了避免因为打印未绑定的变量名而出现错误,最优雅的方法就是不打印它们;第二个优雅的方法是确保这些变量名是绑定的,比如在函数开始时给它们赋一个值(通常用None来表示)。

如果没有,那有没有不优雅的方法呢?

try: print 'b is', b
except NameError: print 'b is not bound'

在一个复杂的函数中,我更倾向于避免在打印调试信息之前,检查每个局部变量是否存在。

保持函数简单(也就是不要复杂)是非常推荐的。正如霍尔在30年前的图灵奖演讲《皇帝的新衣》中所说(可以在这个PDF中找到):

构建软件设计有两种方式:一种是让它简单到显然没有缺陷,另一种是让它复杂到没有明显的缺陷。第一种方法要困难得多。

实现和保持简单确实很难:当你需要实现某个完整功能X时,最自然的诱惑就是通过把各种复杂的类和函数拼凑在一起,使用一些“聪明”的技巧,或者复制粘贴稍微修改一下的方式来完成。

然而,努力保持你的函数“简单到显然没有缺陷”是值得的。如果一个函数很难完全进行单元测试,那说明它太复杂了:你需要把它拆分成更自然的组成部分,尽管这需要一些工作来发现它们。(这实际上是专注于单元测试提高代码质量的一种方式:它不断促使你保持所有代码都能完美测试,同时也促使你让结构简单)。

撰写回答