TL DR - maybe not. But I tried.
It is really strange and looks like turtles. In fact, I still have not delved into this arena, although it sounded fun and powerful. This explanation is confusing, as is the rest of the information on this page, but I feel that I have some enlightenment. Can I explain this, I'm not sure, but I will go.
Look at the turtles, first:
>>> isinstance(type, object) True >>> isinstance(object, type) True
Wait what?
How is an object instance of type when type is an instance of object ? This is similar to saying something like:
class Parrot: pass ex = Parrot() isinstance(ex, Parrot) isinstance(Parrot, ex)
Must be True both times. But obviously not. Even (as Tadh MacDonald-Jensen pointed out)
>>> isinstance(type, type) True
This should tell you that some kind of magic is happening behind the curtains. So for now, let me just completely forget about Python (I know why we would ever want to do such a terrible thing?)
In general, all computer programs are 1 and 0 (and, more precisely, this is just a bunch of logic gates and electrons for> ~ 2.5v and ~ 2.5v, but 0 and 1 are good enough) . If you wrote it in an assembly, the actual machine code, Python, C #, Java, Perl, whatever - they are all just bits.
If you write a class definition, this class is just a bit. An instance of this class is more bits. And a programming language, a compiler, and an interpreter are even more bits.
In the case of Python, it is a python interpreter that gives meaning to the bits that are our Python programs. As an interesting point, many of what we usually see as Python are actually written in Python (although most of them are C, for us they are the people of CPython, Java for Jython, etc.).
So now we come to this thing, which we call type and object . As noted in the article, they are special. So, we know that we can create a class, and then this class is an object:
>>> class Confusion: pass ... >>> isinstance(Confusion, object)
What makes sense if you think about it - you may have created class level variables:
>>> class Counter: ... count = 0 ... def __init__(self): ... Counter.count += 1 ... print(self.count) ... >>> Counter() 1 <__main__.Counter object at 0x7fa03fca4518> >>> Counter() 2 <__main__.Counter object at 0x7fa03fca4470> >>> Counter() 3 <__main__.Counter object at 0x7fa03fca4518> >>> Counter() 4 <__main__.Counter object at 0x7fa03fca4470> >>> Counter.count 4 >>> Counter.__repr__(Counter) '<type object at 0x1199738>'
But since this last example shows (and is mentioned in the message) a class declaration, what you get with class SomeClass: pass , then the class declaration is actually an instance of another class. In particular, it is an instance of the type class. And this instance (which we call the class), when called, produces an instance of itself:
>>> Counter.__call__() 5 <__main__.Counter object at 0x7fa03fca4518>
So, what does all this have to do with the relationship between type and object ?
Well somewhere, python creates a series of object bits and a sequence of type bits, and then connects them so that
>>> type.__bases__ (<class 'object'>,) >>> object.__bases__ ()
Since I donβt want to look at the source now, Iβm going to assume that type is created first, and object is created from this type and that type.__bases__ set to (class 'object') . By creating this circular relationship between type and object , it gives the appearance that itβs just turtles all the way down, when indeed the last two turtles just stand on top of each other.
I donβt think that there is a better way to explain what is happening here than what is described in the article - at least in the classical style of OOP there is a style of thinking, because in fact it is not a thing. Like trying to build a three-dimensional shape in 2d space, you will have problems.
These are just two sets of bits in which there are some bits inside them that are each other's addresses.