当前位置:  开发笔记 > 编程语言 > 正文

类型检查参数Python

如何解决《类型检查参数Python》经验,为你挑选了5个好方法。

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

我使用type(0函数,如:

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

这是一个很好的方法吗?

更新1: Python 3具有函数参数的注释.这些可用于使用工具进行类型检查:http://mypy-lang.org/



1> Johannes Wei..:

使用isinstance().样品:

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


+1来弥补@ nosklo的-1.我不认为它对-1人很酷,因为他们不同意你的实施概念.在许多情况下,类型检查是正确的,特别是因为它是一种重载函数的方法.在设计API以确保用户做正确的事情时,这尤其有用.
isinstance()还检查子类.
http://wiki.python.org/moin/Why%20is%20Python%20a%20dynamic%20language%20and%20also%20a%20strongly%20typed%20language - 第一段的部分说明:在Python中,程序的责任是使用像isinstance()和issubclass()这样的内置函数来测试变量类型和正确使用.Python试图避开你的方式,同时为你提供实现强类型检查所需的一切.

2> SilentGhost..:
>>> isinstance('a', str)
True
>>> isinstance(n, Node)
True


好吧,类型检查是我的应用程序中必须的.我使用OleFileIO_PL并在嵌套列表中返回项列表.如果该项是目录类型,则它是嵌套列表中的列表,如果它是文件,那么它是一个字符串.没有检查字符串,它将是不可能使用.

3> nosklo..:

不,Python中的类型检查参数不是必需的.这绝不是 必要的.

如果您的代码接受地址为rawstring或Node对象,则您的设计会被破坏.

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

Typechecking会损害代码重用并降低性能.具有根据传递的对象的类型执行不同事物的函数是容易出错的,并且具有难以理解和维护的行为.

您有以下更健全的选择:

    创建一个Node接受rawstrings 的对象构造函数,或一个转换Node对象中的字符串的函数.使您的函数假设传递的参数是一个Node对象.这样,如果你需要将一个字符串传递给函数,你只需:

    myfunction(Node(some_string))
    

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

    创建两个函数,一个接受Node对象,另一个接受rawstrings.您可以以最方便的方式在内部调用另一个(myfunction_str可以创建Node对象和调用 myfunction_node,或者相反).

    使Node对象有一个__str__方法并在函数内部调用str()接收到的参数.这样你总是通过强制获得一个字符串.

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


它绝大多数**绝不必要......绝不是.如果您使用python来定义远程接口(例如:XMLRPC),那么在接口处进行强类型检查可能是一个好主意,即使只是为了阻止使用强类型语言(和思维模式)的RPC调用者拥有他们的大脑/脾气暴躁.
在这个答案中非常不必要的讽刺基调.这是一个意见,也包括很多情感包袱.
这是一个非常主观的回应,我很惊讶它被接受为答案.**寻找答案?请看下面的答案**当处理具有彼此通信的对象(非常特定类型的对象)的较大的非平凡的面向对象系统时,类型检查/强制执行可能非常有用.虽然我不提倡类型检查内置类型(list,str等),但允许类/对象使用/依赖于其他类/对象的已定义行为是OOP 101.恕我直言写下所有类型检查为"糟糕的做法"只是限制你作为OOP程序员的能力/力量.
如果Node和str都不是你自己的实现(并且它们可能不在这里),你就不能添加像__str__这样的方法来支持你的替代行为(*).在这种情况下,类型检查是一个明显且可接受的选择,比必须包装每个str实例更可取.
@nosklo:你在其他所有问题上都说"-1 - 没有提到类型检查是一个坏主意".但在你的情况下,-1没有提到它在哪里**正式**做一个类型检查的坏主意.这听起来更像是一种观点,或者借鉴其他一些语言概念.似乎其他人指出了支持类型检查行为的官方声明.
@SubmittedDenied:如果不管类型如何都做同样的事情,那么可以将不同的类型作为参数.
在具有多个开发人员的项目中,插入一些类型断言只是为了包含传递的参数和代码是自我解释是很有用的.
在Python中,程序负责使用内置函数(如isinstance()和issubclass()来测试变量类型和正确使用.Python试图避开你的方式,同时为你提供实现强类型检查所需的一切. - http://wiki.python.org/moin/Why%20is%20Python%20a%20dynamic%20language%20and%20also%20a%20strongly%20typed%20language
如何检查通过线路接收的数据结构(例如,JSON)?我宁愿快速失败,因为我的代码中存在一个特定的信息存在时,会出现更明确的错误.思考?
@SubmittedDenied:不可以.您可以在一个参数中接受多种类型.错误的部分是*检查*你得到的类型,所以你可以做**不同的东西,取决于类型**.
如果这是一个坏主意,那么`inspect`模块可能不是公共标准库.还有更多方法可以检查类型.也可以使用"duck-typing"并对接口执行`getattr`检查而不是类型.有时候这是必要的.

4> John Montgom..:

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

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

有来自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


这比使用类型检查IMO进行攻击更加丑陋且难以维护; 试图将重载函数移植到一种不太适合的语言上.

5> Rob..:

如有必要,您还可以使用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

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


只要不同的行为是相似的(至少在概念上),我看不出有什么大不了的.我们似乎都认为+(在C++中也称为operator +())可以处理数字或字符串,但它实际上具有基于类型的不同行为.
推荐阅读
mylvfamily
这个屌丝很懒,什么也没留下!
DevBox开发工具箱 | 专业的在线开发工具网站    京公网安备 11010802040832号  |  京ICP备19059560号-6
Copyright © 1998 - 2020 DevBox.CN. All Rights Reserved devBox.cn 开发工具箱 版权所有