isinstance(foo,bar)vs type(foo)是bar

时间:2014-02-19 23:08:49

标签: python typechecking

语义问题,真的。

直到最近,如果我不得不对结构进行任何类型检查,我会使用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)时真正失去了什么?

5 个答案:

答案 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()内置函数来测试对象的类型,因为它需要考虑子类。

为了说明,请查看模块菱形中的继承层次结构:

enter image description here

然后根据模块菱形看看下面的python控制台输出:

enter image description here

根据文档,它更通用,可以涵盖更广泛的场景。关于OP的原始问题 - 性能特征并未被视为有利于一个优于另一个的有效理由。两者都不是可读性。

进行更深入的讨论,其中包括对(用回答者的话)的解释“为什么在最近的Python版本中检查类型相等是一种比以前更糟糕的做法”,请看这个高度投票的answer

答案 4 :(得分:0)

type(x)不适用于mypy

至少对我而言,首选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