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 type(obj).__str__
).
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
version of __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
metaclass (or type
if they have no metaclass) so that things like
__call__
get looked up on their metaclass (or on type
itself,
which has the standard implementation of various things). Both type
and object
have the type of type
for the same reason (well, in
theory).
(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
to how object
and type
act.
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.)
|
|