简体   繁体   English

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

[英]isinstance(foo,bar) vs type(foo) is bar

A question of semantics, really.一个语义问题,真的。

Up until recently, if I had to do any typechecking on a structure, I would use type(obj) is list et.直到最近,如果我必须对结构进行任何type(obj) is list ,我会使用type(obj) is list et。 al.阿尔。 However since joining SO I've noticed everyone (and I mean EVERYONE ) uses isinstance(obj,list) instead.但是自从加入 SO 我注意到每个人(我的意思是每个人)都使用isinstance(obj,list)代替。 It seems they are synonymous, and timeit reveals almost IDENTICAL speed between them.似乎它们是同义词,并且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

Indeed even dis agrees they're synonymous, with the exception of type is 's COMPARE_OP事实上,即使dis同意它们是同义词,除了type is 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 

I frankly find it more readable to say if type(foo) is list: than if isinstance(foo,list): , the first is basically just pseudo-code and the second calls some function (which I have to look up every time to be isinstance or instanceof ) with some arguments.坦率地说,我发现if type(foo) is list:if isinstance(foo,list):更具可读性,第一个基本上只是伪代码,第二个调用一些函数(我每次都必须查找是isinstanceinstanceof ) 和一些参数。 It doesn't look like a type cast, and there's no explicit way of knowing whether isinstance(a,b) is checking if b is an instance of a or vice-versa.它看起来并不像一个类型转换,而且也知道是否没有明确的方式isinstance(a,b)被检查是否b是一个实例a ,反之亦然。

I understand from this question that we use isinstance because it's nicer about inheritance.我从这个问题中了解到我们使用isinstance是因为它在继承方面更好。 type(ClassDerivedFromList) is list will fail while isinstance(ClassDerivedFromList,list) will succeed. type(ClassDerivedFromList) is list会失败,而isinstance(ClassDerivedFromList,list)会成功。 But if I'm checking what should ALWAYS BE A BASE OBJECT, what do I really lose from doing type is ?但是,如果我正在检查什么应该始终是基础对象,那么我真正从做type is失去了什么?

if I'm checking what should ALWAYS BE A BASE OBJECT, what do I really lose from doing type is?如果我正在检查什么应该永远是基础对象,那么我真正失去的类型是什么?

well, it's nice you give the full documented answer in your question, so your answer is you lose nothing !好吧,很高兴您在问题中给出了完整的文档答案,所以您的答案是您不会丢失任何东西 The only times where isinstance() is necessary is when checking inheritance of a given class compared to another, as you well said and referenced.唯一需要isinstance()是检查给定类的继承与另一个类的比较时,正如您所说和引用的那样。 type() shall be only used to check whether an instance is exactly of a given base type. type()仅用于检查实例是否完全属于给定的基类型。

Other than the inheritance issue, you also lose the ability to test multiple types when using isinstance .除了继承问题之外,您还无法在使用isinstance时测试多种类型。 For example:例如:

def chk(typ):
    if not isinstance(typ, (str, int)):
        raise ValueError('typ must be string or int')
    ...

The Python Docs for the built-in type function provide clear guidance on the difference between type (with one arg) and isinstance.内置类型函数Python 文档对类型(带有一个参数)和 isinstance 之间的区别提供了明确的指导。

With one argument, return the type of an object.使用一个参数,返回对象的类型。 The return value is a type object and generally the same object as returned by object.返回值是一个类型对象,通常与 object 返回的对象相同。 class . The isinstance() built-in function is recommended for testing the type of an object, because it takes subclasses into account.建议使用 isinstance() 内置函数来测试对象的类型,因为它考虑了子类。

To illustrate, take a look at the inheritance hierarchy below in module diamond:为了说明这一点,请看下面模块菱形中的继承层次结构:

在此处输入图片说明

Then take a look at the python console output below based on module diamond:然后看看下面基于模块diamond的python控制台输出:

在此处输入图片说明

As per the documentation, it is more versatile and can cover a wider range of scenarios.根据文档,它更通用,可以涵盖更广泛的场景。 With respect to the OP's original question - the performance characteristics were not stated as a valid reason to favour one over the other.关于 OP 的原始问题 - 没有将性能特征说明为偏爱另一个的正当理由。 Neither was readability.可读性也不是。

For a more in-depth discussion, which includes an explanation on (in the words of the answerer) "why checking type equality is an even worse practice in recent Python versions than it already used to be" , please see this highly voted answer有关更深入的讨论,其中包括对(用回答者的话) “为什么在最近的 Python 版本中检查类型相等性的做法比以前更糟糕”的解释,请参阅此高度投票的答案

type(x) doesn't work with mypy type(x) 不适用于 mypy

At least for me, the main reason for preferring isinstance over type(x) is because mypy can infer types from isinstance checks but it can't with type(x) .至少对我来说,更喜欢isinstance不是type(x)主要原因是因为 mypy 可以从isinstance检查中推断类型,但它不能使用type(x) From the docs:从文档:

Mypy can usually infer the types correctly when using isinstance type tests, but for other kinds of checks you may need to add an explicit type cast: Mypy 通常可以在使用 isinstance 类型测试时正确推断类型,但对于其他类型的检查,您可能需要添加显式类型转换:

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:
        ...

Source: https://mypy.readthedocs.io/en/stable/common_issues.html?highlight=isinstance#complex-type-tests来源: https : //mypy.readthedocs.io/en/stable/common_issues.html?highlight=isinstance#complex-type-tests

The answer to your question is:你的问题的答案是:
No, given that you're checking for a definite base class, as you loose the ability to test for inherited classes.不,鉴于您正在检查确定的基类,因为您失去了测试继承类的能力。

And IMO isinstance is nicer to read and in Python: Readability counts. IMO isinstance更易于阅读,而且在 Python 中:可读性很重要。

PS: I'm getting a significant difference in timings (on Python 3.3) PS:我在时间上有显着差异(在 Python 3.3 上)

      type: 0.5241982917936874  
isinstance: 0.46066255811928847

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM