为什么Python中的类型检查被认为是一个坏主意?

为什么Python中的类型检查被认为是一个坏主意?,python,typechecking,Python,Typechecking,许多人发表了这样的评论,但没有人给出它不好的原因 如何捕获用户输入错误?等待其他地方的代码“抛出异常?”为什么立即捕获错误不是更好 例如,(ab)用户在17.6中键入预期的整数响应。这显然是一个错误,为预期的int类型获取float类型(只是为了澄清?) 或者,比方说,(ab)用户甚至为预期的浮动输入17/6。17/6是一个浮点值,因此如果等待数据到达实际使用的位置,就很难捕捉到这个错误 我不明白这个前提 =========================== 以下是基于许多(非常好)回复的编辑

许多人发表了这样的评论,但没有人给出它不好的原因

如何捕获用户输入错误?等待其他地方的代码“抛出异常?”为什么立即捕获错误不是更好

例如,(ab)用户在17.6中键入预期的整数响应。这显然是一个错误,为预期的
int
类型获取
float
类型(只是为了澄清?)

或者,比方说,(ab)用户甚至为预期的
浮动输入17/6。17/6是一个
浮点值
,因此如果等待数据到达实际使用的位置,就很难捕捉到这个错误

我不明白这个前提

=========================== 以下是基于许多(非常好)回复的编辑-谢谢所有回复

首先,我相信所有的编码风格都是基于人们的观点,这些观点是基于他们遇到的一些错误。所以,是的,根据定义,因为这是一个编码风格的问题,所有的答案都可能基于观点,或是导致这一问题的经验

第二,在函数中输入后测试类型,这是我从注释中了解到的。非常感谢你的例子和解释

第三,也许“类型测试不好”的思想应该在某种程度上解释为测试输入后的意思,正如许多评论所指出的那样。这是一个笼统的声明,在我所做的许多搜索的回复中都有陈述,试图测试在我的代码中获得的人工输入

再次感谢大家分享的所有知识。

举几个例子

  • 假设您需要将文件传递给函数。您真正想要的是一个类似文件的对象,这意味着您可以在任何您喜欢的对象上实现
    .write()
    方法,并将其传递给函数。检查对象的类型是否错误,您需要的是验证对象是否具有正确的接口

  • 假设您从numpy数组中取出一些数字,并将它们序列化到JSON中的磁盘。哎呀

    import numpy, json
    a = numpy.array([1, 2, 3], numpy.uint16)
    print(json.dumps(a[0]))
    
    当你运行它时

    TypeError: 1 is not JSON serializable
    
    什么?显然,1是JSON可序列化的,但这是一个具有不同类型的1。想象一下跟踪这种错误。谁知道这个数字出现在numpy数组中有多久了

  • 所以您希望进行输入验证,是的,因为这将在错误成为问题之前捕获错误。但是,您不希望简单地依赖对象的类型,因为Python中的类型系统并不表示您实际希望输入的约束类型

    在其他语言中,约定是使用类型系统表示对输入的约束。例如,类文件对象可以在具有此类概念的语言中实现为类型类或接口


    也就是说,如果你真的需要一个
    int

    我不同意类型检查是个坏主意的问题,我不知道为什么会有人做出这样的声明。我发现类型检查非常重要,Python提供了许多内置函数来解决与类型相关的问题。类型的使用通过消除确定值类型的运行时检查来提高代码执行的安全性和性能

    Python是一种语言(并被解释),与静态类型语言(通常被编译)形成对比。根据Python 3.5,该语言在其源代码中支持字节码解释器或编译器尚未支持的代码

    你可能想仔细阅读这个术语,但也可以查看函数和其他

    请举例说明:

    >>> i = 17
    >>> type(i) # get the type of variable i
    <class 'int'>
    >>> float(i) # convert int to float
    17.0
    >>> f = 17.6
    >>> type(f) # get the type of variable f
    <class 'float'>
    >>> type(f) is float # check if variable f is a float
    True
    >>> type(f) is int # check if variable f is an int
    False
    >>> int(f) # convert float to int
    17
    >>> s = "17.6"
    >>> type(s) # get the type of variable s
    <class 'str'>
    >>> float(s) # convert string s to float (or exception if not possible)
    17.6
    >>> type( float(s) )
    <class 'float'>
    
    >i=17
    >>>类型(i)#获取变量i的类型
    >>>浮点(i)#将int转换为浮点
    17
    >>>f=17.6
    >>>类型(f)#获取变量f的类型
    >>>类型(f)为浮点型#检查变量f是否为浮点型
    真的
    >>>类型(f)为int#检查变量f是否为int
    假的
    >>>int(f)#将浮点转换为int
    17
    >>>s=“17.6”
    >>>type(s)#获取变量s的类型
    >>>float(s)#将字符串s转换为float(或异常,如果不可能)
    17.6
    >>>类型(浮球)
    
    要扩展Simeon Visser和我的评论,应始终进行输入验证。然而,使用类型检查来验证输入不是一个好主意,因为这意味着您可能在任意数据上使用
    eval()
    ,这是一个巨大的安全缺陷,正如SO成员Ned Batchelder的文章所解释的

    应尽快执行输入验证,以确保程序的内部功能只接收不需要进一步验证的正常数据。让每个函数都验证它的参数是低效的,并且会使代码膨胀,使其更难阅读和维护。一个类比:输入验证例程就像程序入口处的保安。一旦数据通过了安全检查,程序中的所有函数都可以认为数据是安全的


    Duck类型允许您编写对所需数据类型宽松的函数。这使它们更加灵活和可重用。因此(例如)执行算术的函数不应该关心它们接收到的数据类型,而应该只关心数据支持函数执行的算术运算。这使您不仅可以在整数或浮点上使用相同的函数,还可以在更奇特的数值类型(如分数,甚至多项式)上使用相同的函数。

    Pedantic:17/6是整数,17.0/6或17/6.0是浮点输入应始终进行验证。但是,在代码中的其他地方,duck类型比类型检查更重要。@Kroltan:
    来自uuu future\uuuu导入分部
    Python是一种动态类型语言。您可能想阅读这个术语,但也要查看函数和其他内容。@DietrichEpp很快,但还不是很快,我的注释将无效。类型类解决#2,ser