Python:类型检查装饰器

5
我已经编写了一个类型检查装饰器(使用wraps):
def accepts_func(*types):
    """ 
    top-level decoration, consumes parameters
    """

    def decorator(func):
        """ 
        actual decorator function, consumes the input function
        """

        @wraps(func)
        def check_accepts(*args):
            """ 
            actual wrapper which does some magic type-checking
            """

            # check if length of args matches length of specified types
            assert len(args) == len(types), "{} arguments were passed to func '{}', but only {} " \
                                            "types were passed to decorator '@accepts_func'" \
                .format(len(args), func.__name__, len(types))

            # check types of arguments
            for i, arg, typecheck in izip(range(1, len(args)+1), args, types):
                assert isinstance(arg, typecheck), "type checking: argument #{} was expected to be '{}' but is '{}'" \
                    .format(i, typecheck, type(arg))

            return func(*args)

        return check_accepts

    return decorator

您可以传递任意数量的类型,它会检查传递给func的参数类型是否与在@accepts_func(param_type1, param_type2, ...)中“硬编码”的类型匹配:

@accepts_func(int, str)
sample_func(arg1, arg2):
    ...does something...

到目前为止,它没有任何问题。


然而,由于我不是Python“大师”,我想知道我的解决方案是否适用于“更大”的项目?

我的解决方案中有什么缺点吗? 例如,性能问题、边缘情况下未捕获的错误等等?

如何改进我的解决方案?是否存在更好的、更符合Python风格的解决方案?

注意: 我不会对项目中的每个函数进行类型检查,只会对我认为确实需要类型安全的函数进行检查。该项目在服务器上运行,因此,抛出的错误会出现在日志中,用户看不到。


2
不要在实际代码中使用断言,如果你的脚本是通过python -O启动的,那么断言将被忽略。只在测试中使用它们。 - Pierre Barre
谢谢!你会建议使用什么替代方案吗?比如最佳实践? - daniel451
只需使用if语句。 - Pierre Barre
2个回答

3

我实际上不建议对输入变量进行类型检查。除了性能问题之外,Python是一种动态类型语言,在某些情况下(例如测试),您需要传递一个实现了一些对象属性的对象,这些属性最初计划与您的代码一起使用,并且这将与您的代码正常工作。

一个简单的例子:

class fake_str:
    def __init__(self, string):
        self.string = string

    def __str__(self):
        return self.string

string = fake_str('test')

isinstance(string, str) # False
string # 'test'

为什么不接受一些已经有效的内容呢?

只需允许兼容对象与您的代码一起工作。

宁愿请求原谅,也不要征得许可!


-1
如果你想要类型检查,可以使用Python 3.5及其typing模块,该模块支持内置的类型提示。

http://blog.jetbrains.com/pycharm/2015/11/python-3-5-type-hinting-in-pycharm-5/

编辑:

作为对读者的警告,像Python这样的语言中的类型提示可能很有用,但也会很麻烦。许多Python API具有高度的多态性,接受许多不同类型的参数和可选参数。这些函数的类型签名很复杂,注释它们根本没有帮助。但是对于接受和返回简单类型的简单函数,类型提示只能帮助提高清晰度。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接