Python:类型检查装饰器 [英] Python: type checking decorator

查看:92
本文介绍了Python:类型检查装饰器的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我已经构建了一个类型检查装饰器(带有换行符):

  def accepts_func(* types):

顶层装饰,使用参数


def装饰器(func):

实际装饰器功能,消耗输入函数


@wraps(func)
def check_accepts(* args):

实际包装器做一些魔术类型检查


#检查args的长度是否与指定类型的长度
断言len(args)== len(types), { }参数传递给func'{}',但是只有{} \
类型传递给装饰器'@accepts_func' \
.format(len(args),func .__ name__ ,len(types))

#检查参数类型
是否适用于i,arg,在izip中进行类型检查(范围(1,len(args)+1),args,类型):
assert isinstance(arg,typecheck),类型检查:参数#{}应该是'{}',但是是'{}' \
.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):
...有什么作用...

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






但是,因为我不是Python的专家,所以我想知道我的解决方案是否适合更大的项目吗?



我的解决方案是否有缺点?
例如例如性能问题,边缘情况下未捕获的错误以及其他东西?



有没有办法改善我的解决方案?是否存在更好的,更多的 pythonic解决方案?



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

解决方案

我实际上会不鼓励对输入变量进行类型检查。除了性能之外,Python是一种动态类型化的语言,在某些情况下(例如,测试),您需要传递一个对象,该对象实现最初计划鼓励的对象的某些属性,并且可以与您的代码配合使用。



一个简单的例子:

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

def __str __(self):
return self.string

string = fake_str(' test')

isinstance(string,str)#错误
字符串#'test'

为什么不接受正常工作的东西



只允许兼容的对象与代码一起工作。 / p>

更容易寻求宽恕比权限


I've built a type checking decorator (with 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

You can pass as many types as you want and it checks if the types of the parameters passed to func match the ones that were "hardcoded" in @accepts_func(param_type1, param_type2, ...):

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

It works without any problems so far.


However, since I am not a Python "guru" I would like to know if my solution is appropriate for "bigger" projects?

Are there any downsides in my solution? E.g. like performance issues, uncaught errors in edge cases, and stuff?

Is there a way to improve my solution? Do better, more "pythonic" solutions exist?

Note: I'm not type checking every function in my project, just the ones there I think I really need type safety. The project runs on a server, hence, errors thrown appear in logs and are not visible to the user.

解决方案

I would actually discourage to typecheck input variables. Performance aside, Python is a dynamically typed language and in some cases (testing, for instance) you would need to pass an object that implement some attributes of the object you initially planned to encourted and, that will work fine with your code.

A simple example:

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'

Why would you not accept something that is working ?

Just allow compatible objects to work with your code.

Easier to ask for forgiveness than permission !

这篇关于Python:类型检查装饰器的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆