Add a function to compute a class's method resolution order. This is

easy for 2.2 new-style classes, but trickier for classic classes, and
different approaches are needed "depending".  The function will allow
later code to treat all flavors of classes uniformly.
This commit is contained in:
Tim Peters 2001-09-22 06:10:55 +00:00
parent c377b16d12
commit e0b2d7ac9a
3 changed files with 47 additions and 1 deletions

View File

@ -253,6 +253,14 @@ you can expect to find the following special attributes:
names and values into strings.
\end{funcdesc}
\begin{funcdesc}{getmro}{cls}
Return a tuple of class cls's base classes, including cls, in
method resolution order. No class appears more than once in this tuple.
Note that the method resolution order depends on cls's type. Unless a
very peculiar user-defined metatype is in use, cls will be the first
element of the tuple.
\end{funcdesc}
\subsection{The interpreter stack
\label{inspect-stack}}

View File

@ -163,6 +163,24 @@ def getmembers(object, predicate=None):
results.sort()
return results
# ----------------------------------------------------------- class helpers
def _searchbases(cls, accum):
# Simulate the "classic class" search order.
if cls in accum:
return
accum.append(cls)
for base in cls.__bases__:
_searchbases(base, accum)
def getmro(cls):
"Return tuple of base classes (including cls) in method resolution order."
if hasattr(cls, "__mro__"):
return cls.__mro__
else:
result = []
_searchbases(cls, result)
return tuple(result)
# -------------------------------------------------- source code extraction
def indentsize(line):
"""Return the indent size, in spaces, at the start of a line of text."""

View File

@ -213,3 +213,23 @@ for fname in files_to_clean_up:
os.unlink(fname)
except:
pass
# Test classic-class method resolution order.
class A: pass
class B(A): pass
class C(A): pass
class D(B, C): pass
expected = (D, B, A, C)
got = inspect.getmro(D)
test(expected == got, "expected %r mro, got %r", expected, got)
# The same w/ new-class MRO.
class A(object): pass
class B(A): pass
class C(A): pass
class D(B, C): pass
expected = (D, B, C, A, object)
got = inspect.getmro(D)
test(expected == got, "expected %r mro, got %r", expected, got)