usage of issubclass - python

>>> import sys
>>> sys.version_info
(2, 4, 4, 'final', 0)
>>> class C:
... pass
...
>>> issubclass(C, C)
True
>>> issubclass(C, object)
False
>>> class T(object):
... pass
...
>>> issubclass(T, T)
True
>>> issubclass(T, object)
True
>>>
Question 1> Why C is a subclass of C?
Question 2> what is the base class of C?
Thank you
// Update for Chris Morgan (At least for me, the following manual doesn't help at all)
>>> help(issubclass)
Help on built-in function issubclass in module __builtin__:
issubclass(...)
issubclass(C, B) -> bool
Return whether class C is a subclass (i.e., a derived class) of class B.
When using a tuple as the second argument issubclass(X, (A, B, ...)),
is a shortcut for issubclass(X, A) or issubclass(X, B) or ... (etc.).

Take a look at issubclass(class, classinfo) documentation
Return true if class is a subclass (direct, indirect or virtual) of
classinfo. A class is considered a subclass of itself. classinfo may
be a tuple of class objects, in which case every entry in classinfo
will be checked. In any other case, a TypeError exception is raised.
and to check base class of C use inspect.getmro(cls) function.
Return a tuple of class cls’s base classes, including cls, in method
resolution order.
>>> class C(object):
... pass
...
>>> inspect.getmro(C)
(<class '__main__.C'>, <type 'object'>)
>>>

http://docs.python.org/library/functions.html#issubclass From that link, "A class is considered a subclass of itself."
To answer your second question, C is an "old style" class so it isn't a subclass of object. Include object as the superclass if you want a new style class. See http://www.python.org/doc/newstyle/ for more info.

http://docs.python.org/library/functions.html#issubclass
A class is considered a subclass of itself.
C has no base class
print C.__bases__
()

Related

How does type() function infers type

Im trying to compare types of two objects by using isinstance(obj1, type(obj2)).
However, im not really sure how type infers the typing of an object - or whether theres a chance that the type returned is of an ancestor class.
Given three classes A, B, C. Class B is subclass of A and class C is subclass of B.
class A:
pass
class B(A):
pass
class C(B):
pass
Using type on an object is the same thing as calling obj.__class__. This returns the class to which an instance belongs.
isinstance however also checks for subclasses. So your call isinstance(obj1, type(obj2)) depends on if the two objects are related.
>>> a = A()
>>> b = B()
>>> c = C()
>>> type(c) == type(b)
False
>>> isinstance(c, type(b))
True
Instance c is of type <class '__main__.C'> and b is of type <class '__main__.B'>. So the comparison using type evaluates to False.
A more elaborate example of your approach and using the class directly:
>>> isinstance(c, type(b)) # as C is subclass of B
True
>>> isinstance(c, B) # using the class directly
True
>>> isinstance(b, type(c)) # as b is of parent class B
False
>>> isinstance(b, C) # C is subclass of B, thus b is not an instance of C
False
>>> isinstance(c, type(a)) # C is subclass of B which is subclass of A
True

Inheritance and function overriding in Python

In python, if class C inherits from two other classes C(A,B), and A and B have methods with identical names but different return values, which value will that method return on C?
"Inherits two methods" isn't quite accurate. What happens is that C has a method resolution order (MRO), which is the list [C, A, B, object]. If you attempt to access a method that C does not define or override, the MRO determines which class will be checked next. If the desired method is defined in A, it shadows a method with the same name in B.
>>> class A:
... def foo(self):
... print("In A.foo")
...
>>> class B:
... def foo(self):
... print("In B.foo")
...
>>> class C(A, B):
... pass
...
>>> C.mro()
[<class '__main__.C'>, <class '__main__.A'>, <class '__main__.B'>, <class 'object'>]
>>> C().foo()
In A.foo
MRO order will be followed now, if you inherit A and B in C, then preference order goes from left to right, so, A will be prefered and method of A will be called instead of B

Is MRO order depth-first or breadth-first?

From Python in a Nutshell:
The lookup of an attribute name in a class essentially occurs by visiting ancestor
classes in left-to-right, depth-first order
However,
>>> class A(object): x = 'a'
...
>>> class B(A): pass
...
>>> class C(A): x = 'c'
...
>>> class D(B, C): pass
...
>>> D.x
'c'
>>> D.__mro__
(<class '__main__.D'>, <class '__main__.B'>, <class '__main__.C'>,
<class '__main__.A'>, <type 'object'>)
D.__mro__ lists the classes not in depth-first order, but breadth-first order. So do I misunderstand something?
Ignoring classic classes, Python resolves method and attribute lookups using the C3 linearisation of the class and its parents. The C3 linearisation is neither depth-first nor breadth-first in complex multiple inheritance hierarchies. In some sense, it is:
depth-first until classes are encountered that will share a parent,
and then breadth-first over those
although that is a very loose characterisation.
In particular however, in simple multiple inheritance hierarchies that do not share a parent, it is depth-first (conveniently ignoring object of course, which is always shared)
Simple Example – Depth First
>>> class a_0(object): pass
>>> class a_1(object): pass
>>> class b_0(a_0): pass
>>> class b_1(a_1): pass
>>> class c(b_0, b_1): pass
Then
>>> [x.__name__ for x in c.__mro__]
['c', 'b_0', 'a_0', 'b_1', 'a_1', 'object']
Shared Base Example – Depth then Breadth First
Note that in your example, you have a shared parent (A) which causes B and C to be traversed in a breadth first fashion. If you instead have an evern more complex hierarchy:
>>> class A(object): pass
>>> class B(A): pass
>>> class C(A): pass
>>> class D_0(B, C): pass
>>> class D_1(B, C): pass
>>> class E_0(D_0): pass
>>> class E_1(D_1): pass
>>> class F(E_0, E_1): pass
Then
>>> [x.__name__ for x in F.__mro__]
['F', 'E_0', 'D_0', 'E_1', 'D_1', 'B', 'C', 'A', 'object']
And you will observe that the search is depth first F, E_0, D_0 until it strikes the point where shared base classes are encountered (B and C that are also bases of D_1, at which point the depth first goes sideways to E_1 and depth first from there again.

How to check if object is instance of new-style user-defined class?

Code:
import types
class C(object):
pass
c = C()
print(isinstance(c, types.InstanceType))
Output:
False
What correct way to check if object is instance of user-defined class for new-style classes?
UPD:
I want put additional emphasize on if checking if type of object is user-defined. According to docs:
types.InstanceType
The type of instances of user-defined classes.
UPD2:
Alright - not "correct" ways are OK too.
UPD3:
Also noticed that there is no type for set in module types
You can combine the x.__class__ check with the presence (or not) of either '__dict__' in dir(x) or hasattr(x, '__slots__'), as a hacky way to distinguish between both new/old-style class and user/builtin object.
Actually, this exact same suggestions appears in https://stackoverflow.com/a/2654806/1832154
def is_instance_userdefined_and_newclass(inst):
cls = inst.__class__
if hasattr(cls, '__class__'):
return ('__dict__' in dir(cls) or hasattr(cls, '__slots__'))
return False
>>> class A: pass
...
>>> class B(object): pass
...
>>> a = A()
>>> b = B()
>>> is_instance_userdefined_and_newclass(1)
False
>>> is_instance_userdefined_and_newclass(a)
False
>>> is_instance_userdefined_and_newclass(b)
True
I'm not sure about the "correct" way, but one easy way to test it is that instances of old style classes have the type 'instance' instead of their actual class.
So type(x) is x.__class__ or type(x) is not types.InstanceType should both work.
>>> class Old:
... pass
...
>>> class New(object):
... pass
...
>>> x = Old()
>>> y = New()
>>> type(x) is x.__class__
False
>>> type(y) is y.__class__
True
>>> type(x) is types.InstanceType
True
>>> type(y) is types.InstanceType
False
This tells us True if it is.
if issubclass(checkthis, (object)) and 'a' not in vars(__builtins__):print"YES!"
The second argument is a tuple of the classes to be checked.
This is easy to understand and i'm sure it works.
[edit (object) to(object,) thanks Duncan!]
Probably I can go with elimination method - not checking if object is instance of user-defined class explicitly - isinstance(object, RightTypeAliasForThisCase), but checking if object not one of 'basic' types.

Get base class type in Python

class a:
pass
class b(a):
pass
c = b()
type(c) == a #returns False
Is there an alternative to type() that can check if an object inherits from a class?
Yes, isinstance: isinstance(obj, Klass)
isinstance and issubclass are applicable if you know what to check against. If you don't know, and if you actually want to list the base types, there exist the special attributes __bases__ and __mro__ to list them:
To list the immediate base classes, consider class.__bases__. For example:
>>> from pathlib import Path
>>> Path.__bases__
(<class 'pathlib.PurePath'>,)
To effectively recursively list all base classes, consider class.__mro__ or class.mro():
>>> from pathlib import Path
>>> Path.__mro__
(<class 'pathlib.Path'>, <class 'pathlib.PurePath'>, <class 'object'>)
>>> Path.mro()
[<class 'pathlib.Path'>, <class 'pathlib.PurePath'>, <class 'object'>]
>>> class a:
... pass
...
>>> class b(a):
... pass
...
>>> c = b()
>>> d = a()
>>> type(c) == type(d)
True
type() returns a type object. a is the actual class, not the type

Categories