2016-04-27 65 views
2

我已经建立了一个类型检查装饰(含包装):的Python:类型检查装饰

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的“大师”,我想知道我的解决方案是否适合“更大”的项目?

我的解决方案有什么缺点吗? 例如像性能问题,边缘情况下的未捕获错误以及其他问题?

有没有办法改善我的解决方案?做得更好,还有更多“pythonic”解决方案吗?

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

+2

不要对实际代码使用断言,如果脚本是用python -O启动的,断言将被忽略。只在测试中使用它们。 – user312016

+0

谢谢!你会建议使用什么呢?像最佳实践一样? – daniel451

+0

只需使用if语句 – user312016

回答

1

我实际上不鼓励对输入变量进行类型检查。除了性能外,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' 

为什么你会不会接受的东西,工作

只允许兼容对象处理您的代码。

Easier to ask for forgiveness than permission

-1

如果您想要使用python 3.5及其支持内置类型提示的打字模块进行类型检查。

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

编辑:

以警示读者。用python这样的语言键入提示可能很有用,但也是一种痛苦。很多python API都是高度多态的,接受许多不同类型的不同参数和可选参数。这些功能的类型签名是粗糙并且注释它们根本没有帮助。但是对于简单的函数来说,返回简单类型的类型提示只能帮助提高清晰度。