python, like C++, supports multiple inheritance. While the concept is easy, the hard work is that if a subclass calls a property that it doesn't define itself, in what order does it go to the parent class to find it, especially when more than one of the many parent classes contain that same property.
The order in which attributes are looked up is different for classic and new-style classes. Now let's look at the two different representations of classic and new-style classes separately:
Classics:
#! /usr/bin/python
# -*- coding:utf-8 -*-
class P1():
def foo(self):
print 'p1-foo'
class P2():
def foo(self):
print 'p2-foo'
def bar(self):
print 'p2-bar'
class C1(P1,P2):
pass
class C2(P1,P2):
def bar(self):
print 'C2-bar'
class D(C1,C2):
pass
if __name__ =='__main__':
d=D()
()
()
Results of implementation:
p1-foo
p2-bar
Example of the code, with a diagram drawn for ease of understanding:
From the output of the classic class above, the
When instance d calls foo(), the search order is D => C1 => P1, the
When instance d calls bar(), the search order is D => C1 => P1 => P2
Summarize: The classic class search is in accordance with the "left to right, depth first" way to find the attributes. d First find out if there is a foo method in itself, if not, then find out if there is such a method in the nearest parent class C1, if not, then continue to look up until you find the method in P1, and the search is over.
New Style Class:
#! /usr/bin/python
# -*- coding:utf-8 -*-
class P1(object):
def foo(self):
print 'p1-foo'
class P2(object):
def foo(self):
print 'p2-foo'
def bar(self):
print 'p2-bar'
class C1(P1,P2):
pass
class C2(P1,P2):
def bar(self):
print 'C2-bar'
class D(C1,C2):
pass
if __name__ =='__main__':
print D.__mro__ #Only new-style classes have the __mro__ attribute, which tells what the lookup order will be
d=D()
()
()
Results of implementation:
(<class '__main__.D'>, <class '__main__.C1'>, <class '__main__.C2'>, <class '__main__.P1'>, <class '__main__.P2'>, <type 'object'>)
p1-foo
C2-bar
From the output of the new-style class above, the
When instance d calls foo(), the search order is D => C1 => C2 => P1
When instance d calls bar(), the search order is D => C1 => C2
To summarize: the new style of class searching uses a "breadth-first" approach to find attributes.