类型检查参数Python

时间:2009-04-09 13:57:29

标签: python typechecking

有时需要在Python中检查参数。例如我有一个函数,它接受网络中其他节点的地址作为原始字符串地址或类封装其他节点信息的类。

我使用type(0函数,如:

if type(n) == type(Node):
    do this
elif type(n) == type(str)
    do this

这是一个很好的方法吗?

更新1: Python 3包含函数参数的注释。这些可以使用工具http://mypy-lang.org/

用于类型检查

5 个答案:

答案 0 :(得分:108)

使用isinstance()。样品:

if isinstance(n, unicode):
    # do this
elif isinstance(n, Node):
    # do that
...

答案 1 :(得分:13)

>>> isinstance('a', str)
True
>>> isinstance(n, Node)
True

答案 2 :(得分:7)

不,Python中的类型检查参数不是必需的。它从不 必要的。

如果您的代码接受地址为rawstring或Node对象,那么您的代码就是 设计被打破了。

这是因为如果你不知道一个类型的话 你自己的程序中的对象,那你已经做错了。

Typechecking会损害代码重用并降低性能。有功能 根据传递的对象的类型执行不同的操作 容易出错,行为难以理解和维护。

您有以下更好的选择:

  1. 创建一个接受rawstrings或函数的Node对象构造函数 转换Node个对象中的字符串。让你的功能假设 传递的参数是Node对象。那样的话,如果你需要传递一个 字符串到函数,你只需:

    myfunction(Node(some_string))
    

    这是您最好的选择,它干净,易于理解和维护。 任何阅读代码的人都会立即理解发生的事情, 而且你没有必须进行类型检查。

  2. 制作两个函数,一个接受Node个对象,另一个接受 rawstrings。你最多可以在内部打一个电话 方便的方式(myfunction_str可以创建一个Node对象并调用 myfunction_node,或者相反)。

  3. Node个对象拥有__str__方法并且在您的函数中, 在收到的参数上调用str()。这样你总能得到一个字符串 通过强制。

  4. 无论如何,不要进行类型检查。这是完全没有必要的,只有 缺点。以您不需要进行类型检查的方式重构代码。 无论是短期还是长期,您只能从中获益。

答案 3 :(得分:6)

听起来像是在“泛型函数”之后 - 根据给定的参数表现不同的函数。这有点像你在另一个对象上调用一个方法时会得到一个不同的函数,而不是仅使用第一个参数(对象/ self)来查找函数,而是使用所有参数。

Turbogears使用类似的东西来决定如何将对象转换为JSON - 如果我没记错的话。

使用调度程序包进行此类操作时有an article from IBM

从那篇文章:

import dispatch
@dispatch.generic()
def doIt(foo, other):
    "Base generic function of 'doIt()'"
@doIt.when("isinstance(foo,int) and isinstance(other,str)")
def doIt(foo, other):
    print "foo is an unrestricted int |", foo, other
@doIt.when("isinstance(foo,str) and isinstance(other,int)")
def doIt(foo, other):
    print "foo is str, other an int |", foo, other
@doIt.when("isinstance(foo,int) and 3<=foo<=17 and isinstance(other,str)")
def doIt(foo, other):
    print "foo is between 3 and 17 |", foo, other
@doIt.when("isinstance(foo,int) and 0<=foo<=1000 and isinstance(other,str)")
def doIt(foo, other):
    print "foo is between 0 and 1000 |", foo, other

答案 4 :(得分:6)

如果需要,您还可以使用try catch键入检查:

def my_function(this_node):
    try:
        # call a method/attribute for the Node object
        if this_node.address:
             # more code here
             pass
    except AttributeError, e:
        # either this is not a Node or maybe it's a string, 
        # so behavior accordingly
        pass

您可以在第二个关于生成器(我的版本中的第197页)的 Beginning Python 中看到这样的示例,我相信 Python Cookbook 。很多时候捕获AttributeErrorTypeError更简单,显然更快。此外,它可能以这种方式工作得最好,因为那时你没有绑定到特定的继承树(例如,你的对象可能是Node,或者它可能是与{{1}具有相同行为的其他对象}})。