【问题标题】:Basic Python: Exception raising and local variable scope / binding基本 Python:异常引发和局部变量范围/绑定
【发布时间】:2010-04-30 13:32:19
【问题描述】:

我有一个基本的“最佳实践”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 有没有优雅的方法来处理这个问题?如果不是,那不优雅的方式呢?在一个复杂的函数中,我宁愿避免在打印关于它们的调试信息之前测试每个局部变量的存在。

【问题讨论】:

  • 处理什么? except 子句中应该打印什么?

标签: python exception-handling scope


【解决方案1】:

python 有没有优雅的方法 处理这个?

为了避免打印未绑定名称的异常,最优雅的方法是不打印它们;第二个最优雅的是确保名称确实得到绑定,例如通过在函数开头绑定它们(占位符 None 很受欢迎)。

如果不是,那不优雅的方式呢?

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

在一个复杂的函数中我更喜欢 避免测试存在 I 之前的每个局部变量,对于 例如,打印的调试信息 关于他们

强烈建议您保持函数简单(即复杂)。正如霍尔在 30 年前所写(在他的图灵验收讲座“皇帝的旧衣服”中,转载例如this PDF):

有两种构造方法 软件设计:一种方法是制作它 如此简单,显然没有 不足之处,另一种方法是 让它变得如此复杂以至于有 没有明显的缺陷。首先 方法要困难得多。

实现和保持简单性确实很困难:鉴于您必须实现某个总功能 X,这是世界上最自然的诱惑,通过将复杂的添加到几个复杂的类中来实现,并且各种零碎的功能,“聪明的”黑客,“偷偷摸摸的编码”等的复制粘贴和编辑片段等等。

然而,努力保持你的功能“如此简单以至于显然没有缺陷”是值得的。如果一个函数很难完全进行单元测试,那就太复杂了:将它分解(即重构)成它的自然组件,即使挖掘它们需要工作。 (这实际上是对单元测试的强烈关注有助于提高代码质量的方式之一:通过不懈地激励您保持所有代码完美可测试,同时激励您使其变得简单它的结构)。

【讨论】:

    【解决方案2】:

    你可以在 try 块之外初始化你的变量

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

    【讨论】:

      【解决方案3】:

      您可以使用内置方法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()
      

      【讨论】:

        【解决方案4】:
        def test_function():
           try:
              a = str(5)
              raise
              b = str(6)
           except:
              print b
        

        b = str(6) 永远不会运行;程序在raise 之后退出try 块。如果您想在except 块中打印一些变量,请在引发异常之前对其进行评估并将它们放入您抛出的异常中。

        class MyException(Exception):
           def __init__(self, var):
              self.var = var
        
        def test_function():
           try:
              a = str(5)
              b = str(6)
              raise MyException(b)
           except MyException,e:
              print e.var
        

        【讨论】:

        • 永远不要提出Exception。就像在这种情况下,抓住它永远不会理智。如果你用上面不可调用的东西遮蔽了str,这将捕获TypeError,如果你的内存不足并且无法创建这些对象以及许多其他你无法解释的事情,则会捕获MemoryError
        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2014-07-14
        • 2016-11-13
        • 1970-01-01
        • 2014-03-02
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多