Python's first impression is usually that of a wimpish entity. Macho languages are not interpreted; they are compiled. And they don't offer an interactive shell to write scripts in. To sum up, an interpreted scripting language is considered to be a kid's zone stuff - not to be taken seriously by the OOP community. I had also started out with that impression. After all, peer opinions drive a lot of things in today's world. Then one day, while deep-diving into the architecture of Python to know the beast better, I discovered something odd again. Take a look at this screenshot carefully to spot the paranormal.

The story does not end there. I found this too.

In Python, objects are omnipresent, so much so that even the primitives, like int, char or float, exist as instances of their respective classes. It is to be noted here that even Java allows primitives; Python does not.

I can't believe that a dynamically typed language is so particular about typecasting every identifier into an object. Anyway, if empirical evidence suggests that the class "type" is the Adam of all class-kind, then it should be possible to create an instance of the class "type" itself and examine it.

It looks like the class "type" does not have an empty constructor. Let's figure out what are the arguments one has to pass. A bit of Googling tells me that the first argument is the class name you are trying to create. The other two arguments may be an empty tuple and an empty dict, respectively.

Predictably, Ghost is an instance of the class "type", even though there is nothing predictable about ghosts as such. Conventional logic says that an object would get the attributes and methods of the class from which it is instantiated. Since Ghost is an object, in this case, it should contain some attributes and methods. I would be curious to see what it contains.

I was about to announce that the mystery is resolved. But then another unknown thing cropped up. Note that many of the fields and methods are inherited from the class "object". It looks like when you create a new class you inherit from both object and type. Let's see what "object" is all about.

So there is nothing special about the class "object". It is also like other custom classes, inherited from the class "type". When I created an instance of the class "type, ", why did the fields and methods of the class "object" come along? After some Internet research, I get to know that in the earlier versions of Python (2.x) "object" played the role of Adam. In the later versions (3.x) it changed to "type". The type was introduced to allow meta programming. It may be noted that obj, an instance of "object", is an object. It cannot be instantiated. Whereas an instance of "type" is a class itself, which can be instantiated and potentially changed. The former is kept alive to maintain backward compatibility.

Welcome to the world of meta-programming. In Python, you can create classes dynamically, which is another weird thing. The other weird thing we came across is that a function is also an object. Let's dig that up too.

So a function is an instance of class "method", which in turn is an instance of the class "type". Before I end this article, let me freak you out a bit more with this :