isinstance() and issubclass() return conflicting results

后端 未结 4 1943
既然无缘
既然无缘 2020-12-16 10:39
>>> class Hello:
    pass

and

>>> isinstance(Hello,object)
True
>>> issubclass(Hello,object)
False
>         


        
相关标签:
4条回答
  • 2020-12-16 11:18

    My answer pertains to Python 3.

    To expand upon cbare's answer, the code below was helpful for me.

    >>> class X:
    ...     pass
    ...     
    >>> class Y(X):
    ...     pass
    ...     
    >>> x = X()
    >>> y = Y()
    >>> isinstance(x, X)  # is object x an instance of class X (or any subclass)?
    True
    >>> isinstance(x, Y)  # is object x an instance of class Y (or any subclass)?
    False
    >>> isinstance(y, X)  # is object y an instance of class X (or any subclass)?
    True
    >>> isinstance(y, Y)  # is object y an instance of class Y (or any subclass)?
    True
    
    >>> issubclass(X, X)  # is class X a subclass of X (including class X)?
    True
    >>> issubclass(X, Y)  # is class X a subclass of Y (including class Y)?
    False
    >>> issubclass(Y, X)  # is class Y a subclass of X (including class X)?
    True
    >>> issubclass(Y, Y)  # is class Y a subclass of Y (including class Y)?
    True
    
    >>> issubclass(type(x), X)  # is class of object x a subclass of X (including class X)?
    True
    >>> issubclass(type(x), Y)  # is class of object x a subclass of Y (including class Y)?
    False
    >>> issubclass(type(y), X)  # is class of object y a subclass of X (including class X)?
    True
    >>> issubclass(type(y), Y)  # is class of object y a subclass of Y (including class Y)?
    True
    
    >>> issubclass(x.__class__, X)  # is class of object x a subclass of X (including class X)?
    True
    >>> issubclass(x.__class__, Y)  # is class of object x a subclass of Y (including class Y)?
    False
    >>> issubclass(y.__class__, X)  # is class of object y a subclass of X (including class X)?
    True
    >>> issubclass(y.__class__, Y)  # is class of object y a subclass of Y (including class Y)?
    True
    

    We can see that isinstance(object, class) respects inheritance / subclasses correctly.

    0 讨论(0)
  • 2020-12-16 11:23

    The accepted answer is correct, but seems to miss an important point. The built-in functions isinstance and issubclass ask two different questions.

    isinstance(object, classinfo) asks whether an object is an instance of a class (or a tuple of classes).

    issubclass(class, classinfo) asks whether one class is a subclass of another class (or other classes).

    In either method, classinfo can be a “class, type, or tuple of classes, types, and such tuples.”

    Since classes are themselves objects, isinstance applies just fine. We can also ask whether a class is a subclass of another class. But, we shouldn't necessarily expect the same answer from both questions.

    class Foo(object):
        pass
    
    class Bar(Foo):
        pass
    
    issubclass(Bar, Foo)
    #>True
    isinstance(Bar, Foo)
    #>False
    

    Bar is a subclass of Foo, not an instance of it. Bar is an instance of type which is a subclass of object, therefore the class Bar is an instance of object.

    isinstance(Bar, type)
    #>True
    issubclass(type, object)
    #>True
    isinstance(Bar, object)
    #>True
    
    0 讨论(0)
  • 2020-12-16 11:33

    So basically isinstance(new_object, some_class) returns True if the object is an instantiated class of some_class. In other words, new_object is an some_class() object. issubclass checks if the object has a subclass of some_class.

    Better explained with a simple example that makes perfect sense:

    class some_class():
      pass
    
    class new_object_class(some_class):
      pass
    
    instance_object = new_object_class()
    
    isinstance(instance_object, new_object_class) == True
    issubclass(instance_object, some_class) == True
    
    isinstance(new_object_class,some_class) == True
    issubclass(new_object_class,some_class) == True
    

    No need for false tests to explain this.

    0 讨论(0)
  • 2020-12-16 11:45

    It's because you are using old-style classes so it doesn't derive from object. Try this instead:

    class Hello(object):
        pass
    
    >>> issubclass(Hello,object)
    True
    

    Old-style classes are deprecated and you shouldn't use them any more.

    In Python 3.x all classes are new-style and writing (object) is no longer required.

    0 讨论(0)
提交回复
热议问题