Python - 使用异常提升进行参数检查

S. *_*gee 6 python if-statement exception typechecking

我试图将异常提升代码块写入我的Python代码,以确保传递给函数的参数满足适当的条件(即使参数成为必需,类型检查参数,建立参数的边界值等等).我很满意地理解如何手动引发异常以及处理异常.

from numbers import Number

def foo(self, param1 = None, param2 = 0.0, param3 = 1.0):
   if (param1 == None):
      raise ValueError('This parameter is mandatory')
   elif (not isinstance(param2, Number)):
      raise ValueError('This parameter must be a valid Numerical value')
   elif (param3 <= 0.0):
      raise ValueError('This parameter must be a Positive Number')
   ...
Run Code Online (Sandbox Code Playgroud)

这是Python中可接受的(经过验证的)参数检查方式,但我不得不怀疑:由于Python除了if-then-else语句之外没有编写Switch-case的方法,是否有更有效或更正确的方法执行此任务?或者实施长期if-then-else语句是我唯一的选择?

tob*_*s_k 6

您可以创建一个装饰器函数并将预期的类型和(可选)范围作为参数传递。像这样的东西:

def typecheck(types, ranges=None):
    def __f(f):
        def _f(*args, **kwargs):
            for a, t in zip(args, types):
                if not isinstance(a, t):
                    raise TypeError("Expected %s got %r" % (t, a))
            for a, r in zip(args, ranges or []):
                if r and not r[0] <= a <= r[1]:
                    raise ValueError("Should be in range %r: %r" % (r, a))
            return f(*args, **kwargs)
        return _f
    return __f
Run Code Online (Sandbox Code Playgroud)

相反,if ...: raise您也可以反转条件并使用assert,但正如注释中所述,这些可能并不总是被执行。您还可以扩展它以允许开放范围(例如(0., None))或接受任意(lambda)函数以进行更具体的检查。

例子:

@typecheck(types=[int, float, str], ranges=[None, (0.0, 1.0), ("a", "f")])
def foo(x, y, z):
    print("called foo with ", x, y, z)
    
foo(10, .5, "b")  # called foo with  10 0.5 b
foo([1,2,3], .5, "b")  # TypeError: Expected <class 'int'>, got [1, 2, 3]
foo(1, 2.,"e")  # ValueError: Should be in range (0.0, 1.0): 2.0
Run Code Online (Sandbox Code Playgroud)