这是一篇很经典的文章，介绍 Python 中与 Type 和 Object 相关的概念，不过最近发现源文章好像已经无法访问，所以把发现的一篇 PDF 重新整理成网页。
原作者为 Shalabh Chaturvedi ，这里仅转发，但会使用 Python3 做实验，以飨读者。
Explains Python new-style objects:
New-style implies Python version 2.2 and upto and including 3.x. There have been some behavioral changes during these version but all the concepts covered here are valid. The system described is sometimes called the Python type system, or the object model.
This book is part of a series:
Some points you should note:
So what exactly is a Python object? An object is an axiom in our system - it is the notion of some entity. We still define an object by saying it has:
2has a type
intand the object
"joe"has a type
If you are more of the ‘I like to know how the bits are laid out’ type as opposed to the ‘I like the meta abstract ideas’ type, it might be useful for you to know that each object also has a specific location in main memory that you can find by calling the
The type and bases (if they exist) are important because they define special relationships an object has with other objects. Keep in mind that the types and bases of objects just other objects. This will be re-visited soon.
You might think an object has a name but the name is not really part of the object. The name exists outside of the object in a namespace (e.g. a function local variable) or as an attribute of another object.
Even a simple object such as the number
2 has a lot more to it than meets the eye.
>>> two = 2 <1> >>> type(two) <class 'int'> <2> >>> type(type(two)) <class 'type'> <3> >>> type(two).__bases__ (<class 'object'>,) <4> >>> dir(two) <5> ['__abs__', '__add__', '__and__', '__bool__', '__ceil__', '__class__', '__delattr__', '__dir__', '__divmod__', '__doc__', '__eq__', '__float__', '__floor__', '__floordiv__', '__format__', '__ge__', '__getattribute__', '__getnewargs__', '__gt__', '__hash__', '__index__', '__init__', '__init_subclass__', '__int__', '__invert__', '__le__', '__lshift__', '__lt__', '__mod__', '__mul__', '__ne__', '__neg__', '__new__', '__or__', '__pos__', '__pow__', '__radd__', '__rand__', '__rdivmod__', '__reduce__', '__reduce_ex__', '__repr__', '__rfloordiv__', '__rlshift__', '__rmod__', '__rmul__', '__ror__', '__round__', '__rpow__', '__rrshift__', '__rshift__', '__rsub__', '__rtruediv__', '__rxor__', '__setattr__', '__sizeof__', '__str__', '__sub__', '__subclasshook__', '__truediv__', '__trunc__', '__xor__', 'bit_length', 'conjugate', 'denominator', 'from_bytes', 'imag', 'numerator', 'real', 'to_bytes']
class 进行了统一 (详见 新类 VS. 旧类 中的介绍)，不过在 Python2 中，对于内置的类型其实仍然会显示
<type 'XXX'>，而在 Python3 中则进行了完全统一，也就是上述显示的内容，也就是说两者是等价的。
<1>Here we give an integer the name two in the current namespace.
<2>The type of this object is
<class 'int'>. This
<class 'int'>is another object, which we will now explore. Note that this object is also called just
<class 'int'>is the printable representation.
<3>Hmm.. the type of
<class 'int'>is an object called
<class 'int'>is a tuple containing an object called
<class 'object'>. Bet you didn’t think of checking the
<5>Let’s list all the attributes present on this original integer object - wow that’s alot.
You might say “What does all this mean?” and I might say “Patience! First, let’s goover the first rule.”
Rule #1 Everything is an object
int is an object. This doesn’t mean that just the numbers such as
77 are objects (which they are) but also that there is another object called
int that is sitting in memory right beside the actual integers. In fact all integer objects are pointing to
int using their
__class__ attribute saying “that guy really knows me”. Calling
type() on an object just returns the value of the
Any classes that we define are objects, and of course, instances of those classes are objects as well. Even the functions and methods we define are objects. Yet, as we will see, all objects are not equal.
We now build the Python object system from scratch. Let us begin at the beginning - with a clean slate.
You might be wondering why a clean slate has two grey lines running vertically through it. All will be revealed when you are ready. For now this will help distinguish a slate from another figure. On this clean slate, we will gradually put different objects,and draw various relationships, till it is left looking quite full.
At this point, it helps if any preconceived object oriented notions of classes and objects are set aside, and everything is perceived in terms of objects (our objects) and relationships.
As we introduce many different objects, we use two kinds of relationships to connect. These are the subclass-superclass relationship (a.k.a. specialization or inheritance, “man is an animal”, etc.) and the type-instance relationship (a.k.a instantiation, “Joe is a man”, etc.). If you are familiar with these concepts, all is well and you can proceed, otherwise you might want to take a detour through the section called “Object-Oriented Relationships”.
We examine two objects:
<class 'object'> and
>>> object <1> <class 'object'> >>> type <2> <class 'type'> >>> type(object) <3> <class 'type'> >>> object.__class__ <4> <class 'type'> >>> object.__bases__ <5> () >>> type.__class__ <6> <class 'type'> >>> type.__bases__ <7> (<class 'object'>,)
<2>The names of the two primitive objects within Python. Earlier
type()was introduced as a way to find the type of an object (specifically, the
__class__attribute). In reality, it is both - an object itself, and a way to get the type of another object.
<class 'object'>: the type of
<class 'type'>. We also use the
__class__attribute and verify it is the same as calling
<class 'type'>: interestingly, the type of
<class 'type'>is itself! The
__bases__attribute points to
Let’s make use of our slate and draw what we’ve seen.
These two objects are primitive objects in Python. We might as well have introduced them one at a time but that would lead to the chicken and egg problem - which to introduce first? These two objects are interdependent - they cannot stand on their own since they are defined in terms of each other.
Continuing our Python experimentation:
>>> isinstance(object, object) <1> True >>> isinstance(type, object) <2> True
<1>Whoa! What happened here? This is just Dashed Arrow Up Rule in action. Since
<class 'type'>is a subclass of
<class 'object'>, instances of
<class 'type'>are instances of
<class 'object'>as well.
<2>Applying both Dashed Arrow Up Rule and Dashed Arrow Down Rule, we can effectively reverse the direction of the dashed arrow. Yes, it is still consistent.
If the above example proves too confusing, ignore it - it is not much use anyway.
Now for a new concept - type objects. Both the objects we introduced are type objects. So what do we mean by type objects? Type objects share the following traits:
Usermight represent all users in a system, another once called
intmight represent all integers.
__class__for the new object.
Yes you read that right. Types and classes are really the same in Python (disclaimer: this doesn’t apply to old-style classes or pre-2.2 versions of Python. Back then types and classes had their differences but that was a long time ago and they have since reconciled their differences so let bygones be bygones, shall we?). No wonder the
type() function and the
__class__ attribute get you the same thing.
The term class was traditionally used to refer to a class created by the
class statement. Built-in types (such as
string) are not usually referred to as classes, but that’s more of a convention thing and in reality types and classes are exactly the same thing. In fact, I think this is important enough to put in a rule:
Class is Type is Class The term type is equivalent to the term class in all version of Python >= 2.3.
Types and (er.. for lack of a better word) non-types (ugh!) are both objects but only types can have subcasses. Non-types are concrete values so it does not make sense for another object be a subclass. Two good examples of objects that are not types are the integer
2 and the string
"hello". Hmm.. what does it mean to be a subclass of
Still confused about what is a type and what is not? Here’s a handy rule for you:
Type Or Non-type Test Rule If an object is an instance of
<class 'type'>, then it is a type. Otherwise, it is not a type.
Looking back, you can verify that this is true for all objects we have come across, including
<class 'type'> which is an instance of itself.
<class 'object'>is an instance of
<class 'object'>is a subclass of no object.
<class 'type'>is an instance of itself.
<class 'type'>is a subclass of
Note that we are drawing arrows on our slate for only the direct relationships, not the implied ones (i.e. only if one object is another’s
__class__, or in the other’s
__bases__). This make economic use of the slate and our mental capacity.
Python does not ship with only two objects. Oh no, the two primitives come with a whole gang of buddies.
A few built-in types are shown above, and examined below.
>>> list <1> <class 'list'> >>> list.__class__ <2> <class 'type'> >>> list.__bases__ <3> (<class 'object'>,) >>> tuple.__class__, tuple.__bases__ <4> (<class 'type'>, (<class 'object'>,)) >>> dict.__class__, dict.__bases__ <5> (<class 'type'>, (<class 'object'>,)) >>> mylist = [1, 2, 3] <6> >>> mylist.__class__ <7> <class 'list'>
<2>Its type is
<3>It has one base (a.k.a. superclass),
<6>This is how you create an instance of
<7>The type of a list is
<class 'list'>. No surprises here.
When we create a tuple or a dictionary, they are instances of the respective types.
So how can we create an instance of
mylist? We cannot. This is because
mylist is a not a type.
The built-in objects are, well, built into Python. They’re there when we start Python, usually there when we finish. So how can we create new objects?
New objects cannot pop out of thin air. They have to be built using existing objects.
# In Python 2.x: class C(object): <1> pass # In Python 3.x, the explicit base class is not required, classes are # automatically subclasses of object: class C: <2> pass class D(object): pass class E(C, D): <3> pass class MyList(list): <4> pass
classstatement tells Python to create a new type by subclassing an existing type.
<2>Don’t do this in Python 2.x or you will end up with an object that is an old-style class, everything you read here will be useless and all will be lost.
<3>Multiple bases are fine too.
<4>Most built-in types can be subclassed (but not all).
After the above example,
<class 'object'>, and
Subclassing is only half the story.
obj = object() <1> cobj = C() <2> mylist = [1,2,3] <3>
<1>The call operator (
()) creates a new object by instantiating an existing object.
<2>The existing object must be a type. Depending on the type, the call operator might accept arguments.
<3>Python syntax creates new objects for some built-in types. The square brackets create an instance of
<class 'list'>; a numeric literal creates an instance of
After the above exercise, our slate looks quite full.
Note that by just subclassing
<class 'object'>, the type
C automatically is an instance of
<class 'type'>. This can be verified by checking
C.__class__. Why this happens is explained in the next section.
Some questions are probably popping up in your head at this point. Or maybe they aren’t, but I’ll answer them anyway:
A: Internally, when Python creates a new object, it always uses a type and creates an instance of that object. Specifically it uses the
__init__() methods of the type (discussion of those is outside the scope of this book). In a sense, the type serves as a factory that can churn out new objects. The type of these manufactured objects will be the type object used to create them. This is why every object has a type.
<class 'type'>(the type of
<class 'object'>, the specified base) is used as the type object for creating C.
<class 'object'>(and their subclasses, and so on) will have
<class 'type'>as their type.
Advanced Material Ahead Advanced discussion ahead, tread with caution, or jump straight to the next section.
__metaclass__class attribute as in the following example:
class MyCWithSpecialType(object): __metaclass__ = SpecialType
Now Python will create
MyCWithSpecialType by instantiating
SpecialType, and not
SpecialTypemust be a subclass of
<class 'type'>. Implementation of something like
SpecialTyperequires special care and is out of scope for this book.
__metaclass__- which type object will be used?
A: Good Question. Depends if Python can figure out which one to use. If all the bases have the same type, for example, then that will be used. If they have different types that are not related, then Python cannot figure out which type object to use. In this case specifying a
__metaclass__ is required, and this
__metaclass__ must be a subclass of the type of each base.