Python: show type inheritance - python

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'>)

Related

Why is a python variable, which is declared(assigned a value),of type class?

I declare a variable and assign it an integer value, its type is <class 'int>. Shouldn't that be an object?
If I define a class and instantiate its object, the type of the object is again class.
If I assign a variable to object, the variable is <class 'object> and its type is <class 'type'>
(refer the corresponding shell entries)
To be precise, I want to understand what it means when (in tutorials) it is said that everything in Python is an object, when I can see the that type always says it's a class?
Can anyone please explain this discrepancy?
In Python shell:
1.
>>> a = 1
>>> type(a)
>>> <class 'int'>
>>> class Something:
... pass
...
>
>>> s = Something()
>>> type(s)
>>> <class '__main__.Something'>
>>> t = object
>>> t
>>> <class 'object'>
>
>>> type(t)
>>> <class 'type'>
All values in Python are objects, in the sense that each value has a type associated with it. (Variables themselves to not have types; type(a) simply reports the inherent type of whatever value as assigned to the name a.)
Further, classes themselves are first-class values with their own type. Just as the type of 3 is int, the type of int is type. Even type is a value, with the somewhat surprising feature that the type of type is type.
object is the root of the class hierarchy, so all classes have object as an ancestor. (Just as type has type type, object is the parent of object, which is probably less surprising if you are used to any class being a trivial subclass of itself.) All classes, including object, are instances of type type.
With the definition (not declaration) a = 1, you assign the value 1 (with type int) to the name a.
With s = Something(), you create a value of type Something and assign it to the name s.
With t = object, you assign the value object (with the type type) to the name t.
Hmm..., this is not only a vocabulary question. In Python 3 the object class is a special class whose any other class (including int) derives. Everything is an object could more verbosely be said everything is an instance of a class that is a subclass of object.
The last one says that most classes including object are direct instances of another very special class which it type. In fact in Python all classes are instances of their metaclass, and except for special requirement the standard metaclass is type and metaclasses are expected to be subclasses of type
If we want to go one step further, we realize that as type being a class, is a subclass of object: type.__mro__ gives (<class 'type'>, <class 'object'>). On a strict logical and mathematical point of view, it can be seen as rather weird (the set of all sets cannot exists in set theory). But as the basic types and functions of Python are built-in they are not required to be defined in Python language and we do not fall in a definition loop.

Method resolution order (__mro__) not available in Python3.x?

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.

What is the relationship between Python 3 built-in types?

In python 3 everything is a object. I drew a diagram about relation of classes. Is this diagram correct?
the hard part is about type and object classes. how are they in relation ?
type is a object ? or object is a type ?
>>> x=type
>>> type(x)
<class 'type'>
>>> x=object
>>> type(x)
<class 'type'>
As far as I know, the class relations are kind of like this in Python 3:
Every class is a subclass of object
Every class is an instance of type
Every class is created by the type class or an other metaclass, which derives from type. Because of this every class is an instance of type (including type!) Every class will return True for isinstance(cls, type).
In Python 3, every class is also a subclass from object. Every class or instance will return True for isinstance(cls_or_instance, object)
A special case is metaclasses. A metaclass derives from type, so every metaclass will return True for issubclass(metaclass, type) and isinstance(metaclass, type)
The type object is itself an object. Note though that the inheritance model of python is not the same as in other OO-languges, much of it depends on duck typing rather than inheritance.
Note that type(x) returns the type of the object, that type(object) returns <class 'type'> means nothing more than the type of object (which is the type all objects has) is a type (the type all types are), type itself is a type so the type of it is again type.

Use of object <type 'object'>

In python, we all know that there are the general object type, of which every class is naturally a heir.
If we type object in console, it returns type <'object'>.
>>> object
<type 'object'>
So far, so good.
It is also possible to instantiate a variable of type object
>>> var = object()
>>> var
<object object at 0x021684D8>
My question is:
Is there a reason for the object type being instantiable? Is there any use for this? Or is it just made for the sake of formality?
There is at least one practical reason to instantiate object: it's a quick, easy, and idiomatic way to get a value that will not compare equal to any other value (and will raise an exception of you try an ordering comparison). This makes it a perfect sentinel. For example:
last = object()
for value in iterable:
if value != last:
yield value
last = value
If you used None as a sentinel value, it would do the wrong thing if iterable started with None, but there's no way iterable can start with the brand-new object instance you just created.
However, even if there were no practical use for object instances, consider that every instance of a subclass of an object is an object, so conceptually you're creating object instances all the time--and practically, if you're designing a subclass that uses super() in its __init__ or __new__ this is no longer just conceptual. If object.__init__ were unavailable, or raised, you'd have to create a new do-nothing root class for any hierarchy of cooperative classes just to have a do-nothing base implementation.
Try it
class a:
def __init__(self):
self.num=0
class b:
def __init__(self):
self.num=1
A=a()
B=b()
type(A)
type(B)
It will return it:
<class '__main__.a'>
<class '__main__.b'>
This tells what kind of object is that.

Why do metaclass have a type?

I've little bit test to fully understand metaclass in python.
class Test(object):
pass
print Test.__class__
print Test.__class__.__class__
print Test.__class__.__class__.__class__
All of result is same type. but each of their address is not same
I can't really understand why metaclass has a metaclass recursively.
Explain me please?
Actually, addresses are the same:
>>> id(Test.__class__)
6384576
>>> id(Test.__class__.__class__)
6384576
>>> id(Test.__class__.__class__.__class__)
6384576
Everything is an object in Python, and each object must have a class (it should belong to some type). You can access that class/type reference by __class__ attribute, e.g.:
>>> (1).__class__
<type 'int'>
Everything includes classes itself, which are of class/type called type:
>>> (1).__class__.__class__
<type 'type'>
In the same time type 'type'> is also an object and should reference to some class/type. But since this is kind of special object, its __class__ attribute refers to itself:
>>> (1).__class__.__class__.__class__ is (1).__class__.__class__
True
When you do Test.__class__, you get back the type of Test, which is type (because Test is a class identifier).
type itself is again a class identifier, so you can call __class__ (which is inherited from object) on it and you get back that its type is, again, type because it is a class identifier.
Because you will always get back type which is a class itself, you can do this infinitely many times and will always get back that the current object's type is type.
All classes are classes which means they are derived from a class called class...
All the python's class object is build by the built-in function type(). You could also try this.
>>> T.__class__ == type
True
>>> type(type)
<type 'type'>
The T.class is equal to the build-in function type which is also an object implemented the call function. It's a attribute will be interpret as class(T). As your T class have no base class so type() is used which will return the type object.
You could check the python doc about customizing class creation to get detail about class creation.
To determining the appropriate metaclass
if no bases and no explicit metaclass are given, then type() is used
if an explicit metaclass is given and it is not an instance of type(), then it is used directly as the metaclass
if an instance of type() is given as the explicit metaclass, or bases are defined, then the most derived metaclass is used

Categories

Resources