type() 和 isinstance() 的异同
前言
本文介绍一下 Python 3 中的 type() 函数和 isinstance() 函数的作用,重点介绍它们的区别。
本文中的命令行示范,都是基于以下环境:
- 操作系统: CentOS 7
- Python:
3.7.03.7.9 (更新)
type() 和 isinstance() 的作用
Python 是一个动态类型语言(Dynamically Typed Language)
(注意,不要和动态语言
混淆),所谓动态类型语言,是指在程序运行期间才去做数据类型检查的语言。用动态类型语言编程时,不需要给变量指定数据类型。一个变量,一开始被创建为一个字符串类型,之后可以重新被赋值为一个整形。对于这个变量名本身而言,它只是一个不带类型的标记、一个引用(reference),指向一个具体的对象。既然变量名只是一个不带类型的标记,所以它可以被赋值为任何类型:
|
|
既然一个变量名本身指向的对象可以变化,那么在很多场合就需要检查变量的类型,或者说检查这个变量指向的对象的类型。比如,你定义一个函数,它的参数既可以是一个列表类型,也可以是这个列表元素的类型,那么在函数内,你就需要检查参数类型。
为了检查对象的类型,我们可以用type()
或者isinstance()
这两个 Python 自带的函数:
|
|
Python 中,所有东西都是对象,所以任何类型本身也是对象,它的类型就是type
(这里不是 type 方法,而是 type 这个类):
|
|
type() 和 isinstance() 区别
type()
函数和isinstance()
函数虽然都可以用来检查对象的类型,但两者存在本质的区别:
type
只返回对象的类型,即对象所属的类;isinstance
可以检查一个给定的对象(第一个参数)是否是:- 一个类(第二个参数)的实例 ?
- 或者,是否是一个类(第二个参数)的子类的实例 ?
在实际使用中,两者的差异意味着什么?我们来看一个例子,假设我们自定义了一个类,这个类继承自字典,重载了__str__
函数:
|
|
然后我们定义了一个 A 类型的对象,并分别检查它是否是 A 类型及字典类型:
|
|
可以看到,检查 test 对象是否是 A 类型时,两个函数的结果相同,都是 True,但检查 test 对象是否是 dict 类型时,type
的结果是 False,isinstance
的结果是 True。这是因为isinstance
方法不仅检查对象所属的类,也会检查它继承关系上的所有的类。
通俗的语言更容易理解,假设有一个类叫 “学生”,它有多个子类,表示不同的院系的学生,比如:“计算机系”,“英语系”,“化学系” 等,现在有个学生叫 “张三”,它是 “计算机系” 这个类的对象:type
方法是来检查 “张三” 是哪个系的,isinstance
方法可以检查 “张三” 是不是某个系,或者是不是 “学生”。显然,isinstance(“张三”, “学生”)也是成立的。
另外,isinstance
还支持检查是否是多个类型里的一种,即第二个参数可以是一个元祖:
|
|
性能比较
type
和isinstance
方法在执行性能上也略有差异,我们可以用 Python 的timeit
模块来测试一下两者的性能:
|
|
这里给 test 变量赋上一个字符串,再检查它的类型。isinstance
花的时间比type
略多,其实,理解了两个函数的原理也就能理解性能差异:type
只要检查对象所属的类,isinstance
要沿着类的继承关系往上遍历,如果检查的类型不是对象所属的类型,那么isinstance
方法就会花更多的时间。
需要注意的是,使用type
方法时,有些人会用==
来判断类型,它虽然也可以工作,但不推荐。原因有两点
-
==
用于比较两个对象的内容是否一致,而is
是比较两个变量是否指向同一个对象。type
返回的是类对象,使用is
即可完成比较。 -
==
由于比较的是对象内容,所以要比is
执行得慢:1 2
$ python -m timeit -s "test = 'hello'" "type(test) == int" 5000000 loops, best of 5: 82.6 nsec per loop
结论
isinstance
通常是检查类型的更好方式,它会考虑类的继承关系。在 Python 中,程序员通常要检查的是一个对象是否具有诸如字符串的某个行为,而不是检查它是否是一个准确的字符串类型。所以这种情况用 isinstance(object, str) 更合适。
但另一方面,当你想精确地检查一个对象是某种类型的时候,那就适合用type
方法。并且记住,用is
而不是用==
来进行比较。
「 您的赞赏是激励我创作和分享的最大动力! 」
- 原文链接:https://zhuyinjun.me/2019/talk_about_python_type_and_isinstance/
- 版权声明:本创作采用 CC BY-NC 4.0 国际许可协议,非商业性使用可以转载,但请注明出处(作者、链接),商业性使用请联系作者获得授权。