基本Python:异常提升和局部变量范围/绑定

时间:2010-04-30 13:32:20

标签: python exception-handling scope

我有一个基本的“最佳实践”Python问题。我看到已经有与此问题相关的StackOverflow答案,但是他们陷入了复杂的例子或涉及多个因素。

鉴于此代码:

#!/usr/bin/python

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

test_function()

什么是避免不可避免的“UnboundLocalError:在赋值之前引用的局部变量'b'的最佳方法”我将在异常处理程序中获取?

python是否有一种优雅的方式来处理这个问题?如果不是,那么一种不优雅的方式呢?在一个复杂的函数中,我宁愿在我之前避免测试每个局部变量的存在,例如,打印关于它们的调试信息。

4 个答案:

答案 0 :(得分:10)

  

python是否有一种优雅的方式   处理这个?

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

  

如果没有,那么一种不雅的方式呢?

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

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

强烈建议您保持简单的功能(即复杂)。正如Hoare在30年前写的那样(在他的图灵接受演讲“皇帝的旧衣服”中,例如在this PDF中重印):

  

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

实现和维护简单 确实很难:鉴于你必须实现一定的全部功能X,这是世界上最自然的诱惑,通过复杂的增加到一些复杂的类和各种零碎的功能,“聪明”的黑客,复制粘贴和编辑“驱动编码”等剧集等。

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

答案 1 :(得分:6)

您可以在try块

之外初始化变量
a = None
b = None       
try:
    a = str(5)
    raise
    b = str(6)
except:
    print b

答案 2 :(得分: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()

答案 3 :(得分:1)

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

b = str(6)永远不会运行;程序在try之后退出raise块。如果要在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