Ada*_*ith 25 python typechecking
真的是一个语义问题.
直到最近,如果我不得不对结构进行任何类型检查,我会使用type(obj) is listet.人.然而,自从加入SO后,我注意到每个人(我的意思是每个人)都使用了isinstance(obj,list).它们似乎是同义词,并且timeit在它们之间显示出几乎相同的速度.
def a(): return type(list()) is list
def b(): return isinstance(list(),list)
from timeit import timeit
timeit(a)
# 0.5239454597495582
timeit(b)
# 0.5021292075273176
Run Code Online (Sandbox Code Playgroud)
事实上甚至dis同意他们是同义词,除了type is'sCOMPARE_OP
from dis import dis
dis(a)
# 2 0 LOAD_GLOBAL 0 (type)
# 3 LOAD_GLOBAL 1 (list)
# 6 CALL_FUNCTION 0 (0 positional, 0 keyword pair)
# 9 CALL_FUNCTION 1 (1 positional, 0 keyword pair)
# 12 LOAD_GLOBAL 1 (list)
# 15 COMPARE_OP 8 (is)
# 18 RETURN_VALUE
dis(b)
# 2 0 LOAD_GLOBAL 0 (isinstance)
# 3 LOAD_GLOBAL 1 (list)
# 6 CALL_FUNCTION 0 (0 positional, 0 keyword pair)
# 9 LOAD_GLOBAL 1 (list)
# 12 CALL_FUNCTION 2 (2 positional, 0 keyword pair)
# 15 RETURN_VALUE
Run Code Online (Sandbox Code Playgroud)
我坦率地发现它if type(foo) is list:比说起来更可读if isinstance(foo,list):,第一个基本上只是伪代码而第二个调用一些函数(我必须每次都查找isinstance或者查询instanceof)和一些参数.它看起来不像是类型转换,并且没有明确的方法可以知道是否isinstance(a,b)正在检查是否b是实例,a反之亦然.
我从这个问题中理解我们使用isinstance它,因为它对继承更好.type(ClassDerivedFromList) is list会失败,但isinstance(ClassDerivedFromList,list)会成功.但是,如果我正在检查什么应该始终是一个基础对象,我真的会失去什么type is呢?
zmo*_*zmo 17
如果我正在检查什么应该始终是一个基础对象,那么我在做类型时真正失去了什么?
好吧,你很好地在你的问题中给出完整记录的答案,所以你的答案是你什么都没有失去!isinstance()必要的唯一时间是检查给定类的继承与另一个类的继承,正如您所说和引用的那样.type()应仅用于检查实例是否完全是给定的基本类型.
除了继承问题,您还失去了在使用时测试多种类型的能力isinstance.例如:
def chk(typ):
if not isinstance(typ, (str, int)):
raise ValueError('typ must be string or int')
...
Run Code Online (Sandbox Code Playgroud)
内置类型函数的 Python 文档提供了有关类型(带有一个参数)和 isinstance 之间差异的明确指导。
使用一个参数,返回对象的类型。返回值是一个类型对象,通常与 object 返回的对象相同。班级。建议使用 isinstance() 内置函数来测试对象的类型,因为它考虑了子类。
为了说明这一点,请看一下模块 Diamond 中下面的继承层次结构:
然后看一下下面基于diamond模块的python控制台输出:
根据文档,它更加通用,可以覆盖更广泛的场景。关于OP的原始问题 - 性能特征没有被表述为支持其中一个而不是另一个的有效理由。可读性也不好。
要进行更深入的讨论,其中包括(用回答者的话说)“为什么在最近的 Python 版本中检查类型相等性是一种比以前更糟糕的做法”的解释,请参阅这个高度投票的答案