I am new to python and I am trying to draw the inheritance network for a number of classes. I want to number each class in the drawing showing in what order the class objects are searched for attributes (1=first, 2=second, etc.) in object g = G(). Here is what am trying to simulate:
class A : pass
class C : pass
class B(A,C) : pass
class D(A) : pass
class E(B,C) : pass
class F(C) : pass
class G(D,E,F): pass
I went and made the following network. Is there any way to improve upon it, and have I done it this correctly?
Your diagram is almost right as far as showing the inheritance relationships between the classes you've shown. The arrow from B to E should run in the other direction, but everything else is right.
As for numbering the classes in the diagram based on the order they'll be checked in a lookup on an instance of class G, I suggest calling G.mro(). This will give you a list of the classes in the order they'll be searched.
Here's what I get for your example classes:
[<class '__main__.G'>,
<class '__main__.D'>,
<class '__main__.E'>,
<class '__main__.B'>,
<class '__main__.A'>,
<class '__main__.F'>,
<class '__main__.C'>,
<class 'object'>]
If you want to understand how this order is found, you should read up about the C3 linearization algorithm that Python uses. A good place to start is this article written about the new algorithm when it was introduced in Python 2.3.
Related
I'm trying to look under the hood in idle to wrap my head around python custom classes and how they are stored in memory. Suppose I have the following code:
class Point:
pass
x=Point()
print(x)
Given the following output:
<__main__.Point object at 0x000002A3A071DF60>
I know that since my class consists of no code, when I create an object of type Point, an object of type object is implicitly created from which the Point object x inherits such methods as __str__ etc. However, I cant seem to see the connection ie. when I type dir(x), I dont see any attribute that stores a reference to an object of type object. Am I misunderstanding how it works or is there some attribute that I am unaware of?
There is no (direct) instance of type object involved. When you call Point(), a Point instance is created, and nothing else. Inheritance is a mechanism that operates on classes, not on instances.
Python objects have two properties: Their type and their value. The type of x is Point. The value of x is represented by its __dict__, which is empty (because it has no attributes):
>>> type(x)
<class '__main__.Point'>
>>> x.__dict__
{}
There is no reference to an object instance, because no such instance exists. The inheritance from object manifests in the class Point:
>>> Point.__base__
<class 'object'>
>>> Point.mro()
[<class '__main__.Point'>, <class 'object'>]
So the reason why x can use object methods is because Point inherits from object, not because there's a hidden object instance stored in x. You can see that Point has access to all object methods:
>>> Point.__str__ is object.__str__
True
>>> Point.__init__ is object.__init__
True
# etc...
So, by proxy, x has access to all object methods as well.
you may be looking for Point.__mro__? the method resolution order of the class Point. it tells you in what order python will go looking for methods if you call x.method. in your case this will be:
print(Point.__mro__) # or Point.mro()
# (<class '__main__.Point'>, <class 'object'>)
I wonder about that it seems like that the method resolution order attribute mro is not available in Python 3.x anymore. Using Python 3.5.2 and creating a random class object instance A, built-in or self-implemented, for example
A = dict()
and then calling
A.__mro__
doesnt work, raising
AttributeError: 'A' object has no attribute '__mro__'
I tried to use A.mro(), but this gives the same type of exception.
How do I receive the method resolution order now?
That doesn't work on instances. The error hints that the variable A in question is not bound to a type, but to an instance of class A. types (classes) very much do have __mro__:
>>> int.__mro__
(<class 'int'>, <class 'object'>)
>>> class Foo():
... pass
...
>>> Foo.__mro__
(<class '__main__.Foo'>, <class 'object'>)
Since A is an instance of a type and not the type itself, you can use type(A).__mro__.
Additionally, your code wouldn't have worked in Python 2 either; no, instances didn't have __mro__ there either.
This question already has answers here:
How does Python's super() work with multiple inheritance?
(18 answers)
Closed 9 years ago.
I am new to python programming,
below is the example of parent,child classes,There are two direct super classes (i.e. bases) of C: A and B. A comes before B, so one would naturally think that the super class of C is A. However, A inherits its attribute a from T with value a=0: if super(C,c) was returning the superclass of C, then super(C,c).a would return 0 but its won't?
Could you please help me to understand why its returning 2.why not 0
>>> class T(object):
... a = 0
>>> class A(T):
... pass
>>> class B(T):
... a = 2
>>> class C(A,B):
... pass
>>> c = C()
>>>super(C,c).a
2
Thanks,
Hema
It has to do with Python method resolution order, or MRO. The precise definition of Python's MRO is here: Python 2.3's MRO doc. Edit: this explanation by Guido seems easier to read, and it includes an example exactly like yours.
If you call __mro__ on a class, you'll see the order in which it looks up stuff. In this case:
>>> C.__mro__
(<class '__main__.C'>, <class '__main__.A'>, <class '__main__.B'>, <class '__main__.T'>, <type 'object'>)
So there you can see that it goes to B first, and only then to T. The reason is that it would otherwise be impossible to override attributes from T in B in this structure, and that's unlikely to be the desired behaviour.
Personally I just always avoid this diamond-style inheritance pattern, except of course for object which is the base class of every other class.
In my framework I must assure that when a class inherits from ClassA, it must inherit also from ClassB, with ClassB following ClassA (in order to make overridden methods work [in Django forms]). E.g.
class MyClass(ClassA, ClassB) --> correct
class MyClass(ClassA) --> wrong
class MyClass(ClassB, ClassA) --> wrong
is there a way to make ClassA check that it is followed by ClassB (on startup or at runtime)?
Instead of requiring a specific inheritance order, provide a ClassC that uses the right order instead:
class ClassC(ClassA, ClassB):
You can verify base classes with a metaclass, but that is overkill when a simple base class will do. A metaclass on ClassA would be called for subclasses of ClassA as well, then you simply test the bases parameter for the right orderings.
There is a way to do it after defining the classes. It uses mro() method.
If you have something like this
class A(object):
pass
class B(object):
pass
class C(A,B):
pass
If you print the output of mro you get the following.
print(A.mro(), B.mro(), C.mro())
([<class '__main__.A'>, <type 'object'>],
[<class '__main__.B'>, <type 'object'>],
[<class '__main__.C'>, <class '__main__.A'>, <class '__main__.B'>, <type 'object'>])
A way could be:
if C.mro()[1] == A.mro()[0] and C.mro()[2] == B.mro()[0]:
go ahead
else:
raise Exception
How can I get the parent class(es) of a Python class?
Use the following attribute:
cls.__bases__
From the docs:
The tuple of base classes of a class
object.
Example:
>>> str.__bases__
(<type 'basestring'>,)
Another example:
>>> class A(object):
... pass
...
>>> class B(object):
... pass
...
>>> class C(A, B):
... pass
...
>>> C.__bases__
(<class '__main__.A'>, <class '__main__.B'>)
If you want all the ancestors rather than just the immediate ones, use cls.__mro__.
For versions of Python earlier than 3.5, use inspect.getmro:
import inspect
print inspect.getmro(cls)
Usefully, this gives you all ancestor classes in the "method resolution order" -- i.e. the order in which the ancestors will be checked when resolving a method (or, actually, any other attribute -- methods and other attributes live in the same namespace in Python, after all;-).
The fastest way to get all parents, and in order, is to just use the __mro__ built-in.
For instance, repr(YOUR_CLASS.__mro__).
The following:
import getpass
getpass.GetPassWarning.__mro__
...outputs, in order:
(<class 'getpass.GetPassWarning'>, <type 'exceptions.UserWarning'>, <type 'exceptions.Warning'>, <type 'exceptions.Exception'>, <type 'exceptions.BaseException'>, <type 'object'>)
There you have it. The "best" answer may have more votes but this is so much simpler than some convoluted for loop, looking into __bases__ one class at a time, not to mention when a class extends two or more parent classes. Importing and using inspect just clouds the scope unnecessarily.
New-style classes have an mro method you can call which returns a list of parent classes in method resolution order.
Use bases if you just want to get the parents, use __mro__ (as pointed out by #naught101) for getting the method resolution order (so to know in which order the init's were executed).
Bases (and first getting the class for an existing object):
>>> some_object = "some_text"
>>> some_object.__class__.__bases__
(object,)
For mro in recent Python versions:
>>> some_object = "some_text"
>>> some_object.__class__.__mro__
(str, object)
Obviously, when you already have a class definition, you can just call __mro__ on that directly:
>>> class A(): pass
>>> A.__mro__
(__main__.A, object)
If you want to ensure they all get called, use super at all levels.
If you have a variable and want to get its class and parent classes use type() method which will give class for a variable
val="happy coding"
print(type(val).__mro__)
Output:
(<class 'str'>, <class 'object'>)
This funciton will print the all the classes of an object, while in each step the next object will the left most parent.
def print_root_left(class_):
while True:
print(class_)
# Check there if are no bases then we have reached the root class
if not class_.__bases__:
break
class_=class_.__bases__[0] # use the left most parent
example = "hello"
print_root_left(example.__class__)