首页 文章

在Python中检查类型的规范方法是什么?

提问于
浏览
974

检查给定对象是否属于给定类型的最佳方法是什么?如何检查对象是否继承自给定类型?

假设我有一个对象 o . 我如何检查它是否是 str

9 回答

  • 19
    isinstance(o, str)
    

    Link to docs

  • 1195

    到雨果:

    你可能意味着 list 而不是 array ,但这指向了类型检查的整个问题 - 你不是某种序列或者它是一个单一的对象 . 所以尝试像序列一样使用它 .

    假设您要将对象添加到现有序列,或者如果它是一系列对象,则将它们全部添加

    try:
       my_sequence.extend(o)
    except TypeError:
      my_sequence.append(o)
    

    这方面的一个技巧是如果你正在使用字符串和/或字符串序列 - 这很棘手,因为字符串通常被认为是单个对象,但它也是一系列字符 . 更糟糕的是,因为它实际上是一系列单长度字符串 .

    我通常选择设计我的API,使其只接受单个值或序列 - 它使事情变得更容易 . 如果需要的话,在传递它时,将 [ ] 放在你的单个值附近并不难 .

    (虽然这可能会导致字符串错误,因为它们看起来像(是)序列 . )

  • 152

    如果 ostr ,则 isinstance(o, str) 将返回 true ,或者是从 str 继承的类型 .

    当且仅当 o 是str时, type(o) is str 将返回 true . 如果 o 属于继承自 str 的类型,它将返回 false . ----

  • 16

    您可以使用以下行检查以检查给定值的字符类型:

    def chr_type(chrx):
        if chrx.isalpha()==True:
            return 'alpha'
        elif chrx.isdigit()==True:
            return 'numeric'
        else:
            return 'nothing'
    
    chr_type("12)
    
  • 11

    我认为使用像Python这样的动态语言很酷,你真的不应该检查类似的东西 .

    我只是在你的对象上调用所需的方法并捕获 AttributeError . 稍后,这将允许您使用其他(看似无关的)对象调用您的方法来完成不同的任务,例如模拟对象进行测试 .

    我在使用 urllib2.urlopen() 从网上获取数据时使用了很多东西,它返回一个像object这样的文件 . 这可以反过来传递给几乎任何从文件读取的方法,因为它实现了与真实文件相同的 read() 方法 .

    但我确定有时间和地点使用 isinstance() ,否则它可能不会在那里:)

  • 42

    在提出问题并回答之后,type hints were added to Python . Python中的类型提示允许检查类型,但与静态类型语言的方式完全不同 . Python中的类型提示将预期的参数类型与函数关联,将其作为与函数关联的运行时可访问数据,这样就可以检查类型 . 类型提示语法示例:

    def foo(i: int):
        return i
    
    foo(5)
    foo('oops')
    

    在这种情况下,我们希望为 foo('oops') 触发错误,因为参数的带注释类型是 int . 添加的类型提示不会导致脚本正常运行时发生错误 . 但是,它会向函数添加属性,以描述其他程序可以查询并用于检查类型错误的预期类型 .

    可用于查找类型错误的其他程序之一是 mypy

    mypy script.py
    script.py:12: error: Argument 1 to "foo" has incompatible type "str"; expected "int"
    

    (您可能需要从软件包管理器中安装 mypy . 我不认为它与CPython一起提供,但似乎有一定级别的"officialness" . )

    以这种方式检查类型与静态类型编译语言中的类型检查不同 . 因为类型在Python中是动态的,所以类型检查必须在运行时完成,这会产生成本 - 即使在正确的程序上 - 如果我们坚持认为它是偶然发生的 . 显式类型检查也可能比需要更严格,并导致不必要的错误(例如,参数确实需要完全是 list 类型还是任何可迭代的东西?) .

    显式类型检查的优点是它可以更早地捕获错误并提供比duck类型更清晰的错误消息 . 鸭子类型的确切要求只能用外部文档表示(希望它是彻底和准确的),不兼容类型的错误可能远离它们的起源 .

    Python的类型提示旨在提供一种折衷方案,可以指定和检查类型,但在通常的代码执行期间不需要额外的成本 .

    typing 包提供了类型变量,可以在类型提示中使用它来表达所需的行为,而无需特定类型 . 例如,它包含诸如 IterableCallable 之类的变量,用于指定对具有这些行为的任何类型的需求 .

    虽然类型提示是检查类型的最Pythonic方式,但通常更不用Pythonic来检查类型并依赖于duck typing . 类型提示相对较新,当他们是最恐怖的解决方案时,陪审团仍在继续 . 一个相对无争议但非常一般的比较:类型提示提供了一种可以强制执行的文档形式,允许代码生成更早且更容易理解的错误,可以捕获鸭子输入的错误不能,并且可以静态检查(在不寻常的意义上,但它仍然在运行时之外) . 另一方面,鸭子打字长期以来一直是Pythonic方式,不会强加静态类型的认知开销,不那么冗长,并且会接受所有可行的类型然后一些 .

  • 7

    这里有一个例子,为什么鸭子打字是邪恶的,而不知道它何时是危险的 . 例如:这是Python代码(可能省略了正确的缩进),请注意,通过处理isinstance和issubclassof函数可以避免这种情况,以确保当你真的需要一个鸭子时,你不会得到炸弹 .

    class Bomb:
        def __init__(self):
            ""
    
        def talk(self):
            self.explode()
    
        def explode(self):
            print "BOOM!, The bomb explodes."
    
    class Duck:
        def __init__(self):
            ""
        def talk(self):
            print "I am a duck, I will not blow up if you ask me to talk."    
    
    class Kid:
        kids_duck = None
    
        def __init__(self):
            print "Kid comes around a corner and asks you for money so he could buy a duck."
    
        def takeDuck(self, duck):
            self.kids_duck = duck
            print "The kid accepts the duck, and happily skips along"
    
        def doYourThing(self):
            print "The kid tries to get the duck to talk"
            self.kids_duck.talk()
    
    myKid = Kid()
    myBomb = Bomb()
    myKid.takeDuck(myBomb)
    myKid.doYourThing()
    
  • 4

    检查对象类型的 most Pythonic方法是......不检查它 .

    由于Python鼓励Duck Typing,你应该只是 try...except 以你想要的方式使用对象的方法 . 因此,如果您的函数正在寻找可写文件对象,请不要检查它是 file 的子类,只是尝试使用它的 .write() 方法!

    当然,有时候这些漂亮的抽象会崩溃,而 isinstance(obj, cls) 就是你所需要的 . 但要谨慎使用 .

  • -6

    要检查 ostr 的实例还是 str 的任何子类,请使用isinstance(这将是"canonical"方式):

    if isinstance(o, str):
    

    要检查 o 的类型是否完全是 str (排除子类):

    if type(o) is str:
    

    以下也有效,在某些情况下可能有用:

    if issubclass(type(o), str):
    

    有关相关信息,请参阅Python Library Reference中的Built-in Functions .

    还有一点需要注意:在这种情况下,如果你使用的是python 2,你可能真的想要使用:

    if isinstance(o, basestring):
    

    因为这也会捕获Unicode字符串(unicode不是 str 的子类; strunicode 都是basestring的子类) . 请注意,在python 3中不再存在 basestring ,其中有a strict separation个字符串(str)和二进制数据(bytes) .

    或者, isinstance 接受一个类的元组 . 如果x是任何(str,unicode)的任何子类的实例,则返回True:

    if isinstance(o, (str, unicode)):
    

相关问题