语义问题,真的。
直到最近,如果我不得不对结构进行任何类型检查,我会使用type(obj) is list
et。人。但是,自从加入SO后,我注意到每个人(我的意思是 EVERYONE )使用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
确实,即使dis
同意它们也是同义词,type is
的{{1}}除外COMPARE_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
我坦率地说if type(foo) is list:
比if isinstance(foo,list):
更可读,第一个基本上只是伪代码,第二个调用一些函数(每次都需要查找{{{带有一些参数的1}}或isinstance
)。它看起来不像是类型转换,并且没有明确的方法可以知道instanceof
是否正在检查isinstance(a,b)
是b
的实例还是反之亦然。
我从this question了解到我们使用a
,因为它更适合继承。 isinstance
成功后,type(ClassDerivedFromList) is list
将失败。但是,如果我正在检查什么应该始终是一个基础对象,我在做isinstance(ClassDerivedFromList,list)
时真正失去了什么?
答案 0 :(得分:16)
好吧,你很好地在你的问题中给出完整记录的答案,所以你的答案是你输了没有!唯一需要如果我正在检查什么应该始终是一个基础对象,那么我在做类型时真正失去了什么?
isinstance()
的时间是检查给定类的继承与另一个类的继承,正如您所说和引用的那样。 type()
仅用于检查实例是否完全给定的基本类型。
答案 1 :(得分:6)
除了继承问题之外,在使用isinstance
时,您也无法测试多种类型。例如:
def chk(typ):
if not isinstance(typ, (str, int)):
raise ValueError('typ must be string or int')
...
答案 2 :(得分:0)
你的问题的答案是:
不,因为你正在检查一个明确的基类,因为你没有能力测试继承的类。
IMO isinstance
更易于阅读和Python:可读性很重要。
PS:我在时间上有显着差异(在Python 3.3上)
type: 0.5241982917936874
isinstance: 0.46066255811928847
答案 3 :(得分:0)
Python Docs for the built-in type function提供关于类型(带有一个arg)和isinstance之间差异的明确指导。
使用一个参数,返回对象的类型。返回值是一个类型对象,通常与object返回的对象相同。 class 。 建议使用isinstance()内置函数来测试对象的类型,因为它需要考虑子类。
为了说明,请查看模块菱形中的继承层次结构:
然后根据模块菱形看看下面的python控制台输出:
根据文档,它更通用,可以涵盖更广泛的场景。关于OP的原始问题 - 性能特征并未被视为有利于一个优于另一个的有效理由。两者都不是可读性。
进行更深入的讨论,其中包括对(用回答者的话)的解释“为什么在最近的Python版本中检查类型相等是一种比以前更糟糕的做法”,请看这个高度投票的answer
答案 4 :(得分:0)
至少对我而言,首选isinstance
胜过type(x)
的主要原因是因为mypy可以从isinstance
支票中推断类型,但不能使用type(x)
。从文档中:
在使用isinstance类型时,Mypy通常可以正确推断类型 测试,但是对于其他类型的检查,您可能需要添加显式 输入强制转换:
def f(o: object) -> None:
if type(o) is int:
o = cast(int, o)
g(o + 1) # This would be an error without the cast
...
else:
...
来源:https://mypy.readthedocs.io/en/stable/common_issues.html?highlight=isinstance#complex-type-tests