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

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

有帮助吗?

解决方案

要检查 o str 的实例还是 str 的任何子类,请使用 isinstance (这将是”规范“方式):

if isinstance(o, str):

检查 o 的类型是否完全是 str (不包括子类):

if type(o) is str:

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

if issubclass(type(o), str):

有关相关信息,请参阅Python Library Reference中的内置函数

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

if isinstance(o, basestring):

因为这也会捕获Unicode字符串( unicode 不是 str 的子类; str unicode 都是 basestring )。请注意, basestring 不再存在于python 3中,其中字符串的严格分离 str )和二进制数据( bytes )。

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

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

其他提示

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

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

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

如果 o str 或属于某种类型,

isinstance(o,str)将返回 True 继承自 str

type(o)是str 将返回 True 当且仅当 o 是str时。如果 o 属于继承自 str 的类型,它将返回 False

在提出问题并回答问题后,将类型提示添加到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一起提供,但似乎有一定程度的“官方性”。)

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

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

Python的类型提示旨在提供一种折衷方案,可以指定和检查类型,但在通常的代码执行过程中没有额外的成本。

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

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

这是一个例子,为什么鸭子打字是邪恶的,而不知道它何时是危险的。 例如:这是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()
isinstance(o, str)

链接到文档

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

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

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

但我确信使用 isinstance()有时间和地点,否则它可能不存在:)

到雨果:

你可能指的是 list 而不是 array ,但这指的是类型检查的整个问题 - 你不想知道相关的对象是否是列表,你想知道它是某种序列还是它是一个单一的对象。所以尽量像序列一样使用它。

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

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

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

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

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

对于更复杂的类型验证,我喜欢 typeguard 的基于python类型提示注释的验证方法:

from typeguard import check_type
from typing import List

try:
    check_type('mylist', [1, 2], List[int])
except TypeError as e:
    print(e)

您可以以非常干净和可读的方式执行非常复杂的验证。

check_type('foo', [1, 3.14], List[Union[int, float]])
# vs
isinstance(foo, list) and all(isinstance(a, (int, float)) for a in foo) 

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

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

chr_type("12)
许可以下: CC-BY-SA归因
不隶属于 StackOverflow
scroll top