如何检查对象是否为给定类型,或是否从给定类型继承?
如何检查对象o是否为str类型?
初学者通常错误地期望字符串已经是“数字”——要么期望Python 3.x输入转换类型,要么期望像“1”这样的字符串同时也是整数。对于这些问题,这是错误的规范。请仔细阅读问题,然后使用How do I check if a string representative a number(float or int)?,如何将输入读取为数字?和/或询问用户输入,直到他们给出适当的有效响应。
如何检查对象是否为给定类型,或是否从给定类型继承?
如何检查对象o是否为str类型?
初学者通常错误地期望字符串已经是“数字”——要么期望Python 3.x输入转换类型,要么期望像“1”这样的字符串同时也是整数。对于这些问题,这是错误的规范。请仔细阅读问题,然后使用How do I check if a string representative a number(float or int)?,如何将输入读取为数字?和/或询问用户输入,直到他们给出适当的有效响应。
当前回答
在问题被询问和回答之后,类型提示被添加到Python中。Python中的类型提示允许检查类型,但与静态类型语言的方式非常不同。Python中的类型提示将预期的参数类型与函数关联,作为与函数关联的运行时可访问数据,这允许检查类型。类型提示语法示例:
def foo(i: int):
return i
foo(5)
foo('oops')
在这种情况下,我们希望为foo('ops')触发一个错误,因为参数的注释类型是int。当脚本正常运行时,添加的类型提示不会导致错误发生。但是,它向函数中添加了描述其他程序可以查询并用于检查类型错误的预期类型的属性。
可以用来查找类型错误的其他程序之一是mypy:
mypy script.py
script.py:12: error: Argument 1 to "foo" has incompatible type "str"; expected "int"
(您可能需要从软件包管理器中安装mypy。我认为它不随CPython一起提供,但似乎具有某种程度的“官方性”。)
这种方式的类型检查不同于静态类型编译语言中的类型检查。因为Python中的类型是动态的,所以必须在运行时进行类型检查,如果我们坚持在每一个机会都进行类型检查的话,这会增加成本——甚至对正确的程序也是如此。显式类型检查也可能比所需的更具限制性,并导致不必要的错误(例如,参数真的需要完全是列表类型吗,或者任何东西都可以迭代吗?)。
显式类型检查的好处是它可以比鸭子键入更早地捕获错误,并给出更清晰的错误消息。鸭子类型的确切需求只能用外部文档来表达(希望它是彻底和准确的),不兼容类型的错误可能发生在远离它们起源的地方。
Python的类型提示旨在提供一种折衷方案,即可以指定和检查类型,但在通常的代码执行过程中没有额外的成本。
类型化包提供了类型变量,可以在类型提示中使用这些变量来表达所需的行为,而不需要特定的类型。例如,它包含Iterable和Callable等变量,用于提示,以指定对具有这些行为的任何类型的需要。
虽然类型提示是检查类型的最Python方式,但完全不检查类型并依赖于duck类型通常更为Python。类型提示是相对较新的,陪审团还没有确定它们是最符合Python的解决方案。一个相对没有争议但非常普遍的比较:类型提示提供了一种可以强制执行的文档形式,允许代码更早生成更容易理解的错误,可以捕捉鸭子键入无法捕捉的错误,并且可以静态检查(在不寻常的意义上,但它仍然在运行时之外)。另一方面,duck类型很长一段时间以来一直是Python式的方式,不会强加静态类型的认知开销,不那么冗长,并且会接受所有可行的类型,然后接受一些类型。
其他回答
使用isinstance检查o是str的实例还是str的任何子类:
if isinstance(o, str):
要检查o的类型是否正好是str,不包括str的子类:
if type(o) is str:
有关相关信息,请参见Python库参考中的内置函数。
检查Python 2中的字符串
对于Python 2,这是检查o是否为字符串的更好方法:
if isinstance(o, basestring):
因为这也将捕获Unicode字符串。unicode不是str的子类;str和unicode都是basestring的子类。在Python3中,basestring不再存在,因为字符串(str)和二进制数据(字节)有严格的分隔。
或者,isinstance接受一个类元组。如果o是(str,unicode)的任何子类的实例,则返回True:
if isinstance(o, (str, unicode)):
isinstance(o, str)
链接到文档
对于更复杂的类型验证,我喜欢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)
在问题被询问和回答之后,类型提示被添加到Python中。Python中的类型提示允许检查类型,但与静态类型语言的方式非常不同。Python中的类型提示将预期的参数类型与函数关联,作为与函数关联的运行时可访问数据,这允许检查类型。类型提示语法示例:
def foo(i: int):
return i
foo(5)
foo('oops')
在这种情况下,我们希望为foo('ops')触发一个错误,因为参数的注释类型是int。当脚本正常运行时,添加的类型提示不会导致错误发生。但是,它向函数中添加了描述其他程序可以查询并用于检查类型错误的预期类型的属性。
可以用来查找类型错误的其他程序之一是mypy:
mypy script.py
script.py:12: error: Argument 1 to "foo" has incompatible type "str"; expected "int"
(您可能需要从软件包管理器中安装mypy。我认为它不随CPython一起提供,但似乎具有某种程度的“官方性”。)
这种方式的类型检查不同于静态类型编译语言中的类型检查。因为Python中的类型是动态的,所以必须在运行时进行类型检查,如果我们坚持在每一个机会都进行类型检查的话,这会增加成本——甚至对正确的程序也是如此。显式类型检查也可能比所需的更具限制性,并导致不必要的错误(例如,参数真的需要完全是列表类型吗,或者任何东西都可以迭代吗?)。
显式类型检查的好处是它可以比鸭子键入更早地捕获错误,并给出更清晰的错误消息。鸭子类型的确切需求只能用外部文档来表达(希望它是彻底和准确的),不兼容类型的错误可能发生在远离它们起源的地方。
Python的类型提示旨在提供一种折衷方案,即可以指定和检查类型,但在通常的代码执行过程中没有额外的成本。
类型化包提供了类型变量,可以在类型提示中使用这些变量来表达所需的行为,而不需要特定的类型。例如,它包含Iterable和Callable等变量,用于提示,以指定对具有这些行为的任何类型的需要。
虽然类型提示是检查类型的最Python方式,但完全不检查类型并依赖于duck类型通常更为Python。类型提示是相对较新的,陪审团还没有确定它们是最符合Python的解决方案。一个相对没有争议但非常普遍的比较:类型提示提供了一种可以强制执行的文档形式,允许代码更早生成更容易理解的错误,可以捕捉鸭子键入无法捕捉的错误,并且可以静态检查(在不寻常的意义上,但它仍然在运行时之外)。另一方面,duck类型很长一段时间以来一直是Python式的方式,不会强加静态类型的认知开销,不那么冗长,并且会接受所有可行的类型,然后接受一些类型。
检查类型的一个简单方法是将其与您所知道的类型进行比较。
>>> a = 1
>>> type(a) == type(1)
True
>>> b = 'abc'
>>> type(b) == type('')
True