An operational explanation of Python types
In the world of new style classes, everything in Python has a type
(visible with '
type(thing)'); class instances have a type, classes
have a type, even
type() has itself as a type.
Sure, fine, but what does it mean in Python to have a type? What do
types actually do?
Given part 4 of what you can do with metaclasses, we can now see the answer: an object's type is where Python finds special methods for it.
Python does not look for special methods through the
normal attribute lookup process (where it would effectively look up
obj.__str__ if you did
str(obj)); instead it goes straight to the
type (doing the equivalent of
Here, let's have an example:
class Example(object): def __str__(self): return "class" ei = Example() ei.__str__ = lambda x: "lambda" print ei.__str__(ei), str(ei)
This will print '
lambda class', showing that
str() is not using the
__str__ on the object itself.
Now we can see why everything in Python has the type that it does.
Instances of a class have a
type() of their class so that special
methods are looked up on their class, which lets classes actually
implement all of those special methods. Classes have a
type() of their
type if they have no metaclass) so that things like
__call__ get looked up on their metaclass (or on
which has the standard implementation of various things). Both
object have the type of
type for the same reason (well, in
(My example above was contrived because people generally don't try to put special methods on instances. But it's easy to have a clash between a class special method and a metaclass special method, and then this does matter.)
One of the nice aspects of this is that it unifies how Python does
attribute lookup for instances of classes with how it does it with
classes. There is no special magic in the interpreter to treat them
differently; how they behave is just determined by how their type
acts. Much of what looks like fundamental behavior (such as using
Example()' to create an instance of the class) is in fact simply due
Types also get involved in explicit attribute lookups, but that's a much more complicated topic and is not as core to what a type is in Python. (Well, in my opinion.)