1. 关于本篇文章
解释了Python中的新风格objects:
- <type ‘type’>和<type ‘object’>是什么。
- 用户自定义的类和实例之间、用户自定义的类和实例与内建类型之间是如何关联的。
- 元类(metaclasses)是什么。
新风格是指Python 2.2到Python 3.x之间。在这些版本间有一些特性发生了改变,但本文中提到的这些概念都是通用的。本文中描述的内容有时被称为Python type system或者object model。
译者注:object is a base for all new style classes
2. 基本概念
2.1 Python中的object
那么Python object究竟是什么东西?Object是Python中的公理 – 它代表实体。但我们仍然可以通过下面几条来定义Python中的object:
- 有标识(例如,给定两个名字我们可以确定它们是否指向同一个object)
- 有值(value)
- 有类型(type)
- 一个或多个bases.在面向对象中,你可以把这里的bases理解为基类或者超类。
如果你是那种追根究底的人,想知道object的内部机制,那么在这里我在讲一个知识点:每一个object都位于内存之中,通过id()这一函数可以获取object的地址值。
Type和bases(如果存在的话)的概念之所以重要,是因为它们定义了object和其他objects之间的relationship。记住,objects的types和bases也是objects。后面我还会提到这一点。
你可能会认为object有名字,但实际上名字并不是object的一部分。名字存在于object之外,名字存在于命名空间或者作为另一个object的属性。
即便像数字‘2’这样一个简单的例子,其背后的机制远不像表面上看起来的这么简单。
Example 1.1. Examining an integer object
>>> two = 2>>> type(two) <type 'int'>
>>> type(type(two)) <type 'type'>
>>> type(two).__bases__ (<type 'object'>,)
>>> dir(two)
['__abs__', '__add__', '__and__', '__class__', '__cmp__', '__coerce__', '__delattr__', '__div__', '__divmod__', '__doc__', '__float__', '__floordiv__', '__format__', '__getattribute__', '__getnewargs__', '__hash__', '__hex__', '__index__', '__init__', '__int__', '__invert__', '__long__', '__lshift__', '__mod__', '__mul__', '__neg__', '__new__', '__nonzero__', '__oct__', '__or__', '__pos__', '__pow__', '__radd__', '__rand__', '__rdiv__', '__rdivmod__', '__reduce__', '__reduce_ex__', '__repr__', '__rfloordiv__', '__rlshift__', '__rmod__', '__rmul__', '__ror__', '__rpow__', '__rrshift__', '__rshift__', '__rsub__', '__rtruediv__', '__rxor__', '__setattr__', '__sizeof__', '__str__', '__sub__', '__subclasshook__', '__truediv__', '__trunc__', '__xor__', 'conjugate', 'denominator', 'imag', 'numerator', 'real']
也许你会问了:上面这个例子究竟说明了什么?大家不要着急,我先来说说下面这条规则:
Rule 1
Everything is an object
内建的int类型是一个object。但这并不代表仅仅是像2或者77这样的数字是objects,实际上还有另一个叫做int的object,它被保存在那些数字的值旁边(译者注:实际上,像int这种type object,多次运行id(int),其返回值是不会改变的)。所有的整型objects都有 __class__这一属性,而
__class__值就是指向int的,用来表明“那家伙(int)懂我”。type()函数便是返回一个object的
__class__属性值。
我们定义的任何类都是objects。当然,这些类的实例也都是objects。甚至函数和方法也是objects。当然,各个objects并非是完全相同的。
2.2 A Clean Slate
现在我们从零开始构造Python的object system。先从一个空表格开始。
你也许会好奇为什么我要画这样一个图,这只是一个空图,后面我会逐步在上面加上不同的objects,并画出它们间的关系。(译者注:这里的三列从左到右分别代表metaclass,class,instance。metaclass可以理解成class的模板,一个class根据metaclass作为模板而生成出来。)
此时,让我们把之前我们了解的OOP知识先放一边,先从objects(我们定义的objects)和relationships开启此次学习之旅。
2.3 对象间的关系
我们使用两种relationships来连接不同的objects。一种是子类-父类(如:人是一种动物),一种是类型-实例(如Joe是一个人)。如果你对此概念不熟悉,可以先看看这里 the section called “Object-Oriented Relationships”。
3. 引入对象
3.1 The First Objects
<type 'object'>
and <type 'type'>
.Example 2.1. Examining
<type 'object'>
and <type 'type'>
Figure 2.1. Chicken and Egg

这两个objects是Python中的基础object。如果我将它们两个分开介绍的话,就会出现’先有鸡还是先有蛋’的问题 – 究竟该从哪个开始介绍?实际上这两个objects是互相依赖的 – 它们的定义中互相包含。
那么现在继续我们的试验:
![]() |
Whoa! What happened here? This is just Dashed Arrow Up Rule in action. Since <type 'type'> is a subclass of <type 'object'> , instances of <type 'type'> are instances of <type 'object'> as well. |
![]() |
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. |
The solid arrow is the issubclass relationship. The dashed arrow is the isinstance relationship. The dashed arrow could be double ended, but that is not necessary because it automatically follows from the other relationships (Example 2.2).
While subclassing an instance makes no sense in C++, in Python all classes are techincally instances and so subclassing makes sense.
If coming from C++, you basically have to forget the C++ concept of classes and assume all Python classes, meta-classes and objects are like C++ instances. All these ‘instances’ are located in memory and hold references to each other. There are two kinds of references (or edges in this graph of objects) – isinstance and issubclass. How the objects are connected determine how they behave.
Anyway, parts of this book seem too pedantic now and can probably be reduced or simplified.
总是,作者就是为了说明:
Class is Type is Class
type和class这两个术语在所有Python >= 2.3的版本中是一样的。
(译者注:然后作者又来唠叨了,其实这不是废话么?用过C++或者Java的都知道吧,不就是程序中要么是class要么是instance么。只是在Python中,class也是object而已。)
还对判断类对象和非类对象感觉混淆吗?有一个简单的规则:
-
Type Or Non-type Test Rule
- 如果一个对象是<type ‘type’>的实例, 那它就是类对象. 否则是非类对象。
回头看,可以证明这个规则对我们所碰到的所有对象都是成立的, 包括 <type ‘type’>,它是自己的实例.
总结一下:
-
<type ‘object’> 是 <type ‘type’>的一个实例.
-
<type ‘object’> 不是任何类的子类.
-
<type ‘type’> 是自己的实例.
-
<type ‘type’> 是 <type ‘object’>的子类.
- python中只有两种对象: 为了清楚叫它们types 和 non-types. Non-types 也可以叫实例, 但实例这个术语也可以指向一个类对象, 因为一个type一定是另一个的type的实例. Types 也被叫做 classes, 并且我经常把他们叫做classes.
-
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.
3.2 更多内置类型
Python中不止这两个对象,这两个基本对象有一堆的兄弟。
Figure 2.2. Some Built-in Types

上图就是说明:list tuple dict这些类型都是从object继承过来的,然后这些类型是<type ‘type’>的实例。
下面是一些built-in类型的例子。
Example 2.3. Examining some built-in types
当我们创建一个tuple或者dictionary,它们便是各自类型的实例。
那么我们怎么创建一个称之为mylist的实例呢?现在还不能,因为我们还有创建mylist这一类型。
3.3 New Objects by Subclassing
新的objects不会从石头缝里自己冒出来。我们通过已存在的objects来创建新的objects。
Example 2.4. Creating new objects by subclassing
After the above example, C.__bases__
contains <type 'object'>
, and MyList.__bases__
contains <type 'list'>
.
在上例中,C.__bases__包含<type ‘object’>,MyList.__bases__
包含 <type 'list'>。
3.4 New Objects by Instantiating
除了继承外,还有别的方式创建新的object。(译者注:继承就是生成新的type-object,而这里所说的别的方式是指通过类生成新的实例)
Example 2.5. Creating new objects by instantiating
After the above exercise, our slate looks quite full.
通过上面的这些例子,我们的示意图基本上画好了。
Figure 2.3. User Built Objects

我们注意C通过继承自<type ‘object’>的object,其type会是<type ‘type’>的实例,并且是自动成为<type ‘type’>的实例。在下一节我会解释为什么。
3.5 It’s All Instantiation, Really
Q: | How does Python really create a new object? |
A: | Internally, when Python creates a new object, it always uses a type and creates an instance of that object. Specifically it uses the __new__() and __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. |
Q: | When using instantiation, I specify the type, but how does Python know which type to use when I use subclassing? |
A: | It looks at the base class that you specified, and uses its type as the type for the new object. In the exampleExample 2.4, “Creating new objects by subclassing” , <type 'type'> (the type of <type 'object'> , the specified base) is used as the type object for creating C .A little thought reveals that under most circumstances, any subclasses of <type 'object'> (and their subclasses, and so on) will have <type 'type'> as their type. |
Advanced Material Ahead
下面是一些高级内容,你可以直接跳到下一章。
最后我们得到了一个完整的示例图。
Figure 3.1. The Python Objects Map

这里我标出了图片中划分的三个区域分别对应的是什么,他们分别是metaclasses,classes,instances。
我们发现, <type 'type'>是所有类型的type,<type 'object'>是所有类型的基类。
总结上述内容:
- Python中有两种object:
- Type objects – 可以被继承,可以用来创建实例。
- Non-type objects – 不可以被继承,不可以用来创建实例。
<type 'type'>
和<type 'object'>
是两个最基础的object。objectname.__class__
存在于每个object中,且指向此object的type。objectname.__bases__
存在于每个type object中,且指向自己的父类。只有<type ‘object’>的__bases__为空。- To create a new object using subclassing, we use the
class
statement and specify the bases (and, optionally, the type) of the new object. This always creates a type object. - To create a new object using instantiation, we use the call operator (
()
) on the type object we want to use. This may create a type or a non-type object, depending on which type object was used. - Some non-type objects can be created using special Python syntax. For example,
[1, 2, 3]
creates an instance of<type 'list'>
. - Internally, Python always uses a type object to create a new object. The new object created is an instance of the type object used. Python determines the type object from a
class
statement by looking at the bases specified, and finding their types. issubclass(A,B)
(testing for superclass-subclass relationship) returnsTrue
iff:B
is inA.__bases__
, orissubclass(Z,B)
is true for anyZ
inA.__bases__
.
isinstance(A,B)
(testing for type-instance relationship) returnsTrue
iff:B
isA.__class__
, orissubclass(A.__class__,B)
is true.
- Squasher is really a python. (Okay, that wasn’t mentioned before, but now you know.)
The following example shows how to discover and experiment with built-in types.
Example 3.1. More built-in types
>>> import types>>> types.ListType is list
True >>> def f():
... pass ... >>> f.__class__ is types.FunctionType
True >>> >>> class MyList(list):
... pass ... >>> class MyFunction(types.FunctionType):
... pass ... Traceback (most recent call last): File "<stdin>", line 1, in ? TypeError: type 'function' is not an acceptable base type >>> dir(types)
['BooleanType', 'DictProxyType', 'DictType', ..]
So we can create new objects with any relationship we choose, but what does it buy us?
The relationships between objects determine how attribute access on the object works. For example, when we sayobjectname.attributename
, which object do we end up with? It all depends on objectname
, its type, and its bases (if they exist).
Attribute access mechanisms in Python are explained in the second book of this series: Python Attributes and Methods.
This is a note about classic classes in Python. We can create classes of the old (pre 2.2) kind by using a plain class statement.
The types.ClassType
object is in some ways an alternative <type 'type'>
. Instances of this object (classic classes) are types themselves. The rules of attribute access are different for classic classes and new-style classes. Thetypes.ClassType
object exists for backward compatibility and may not exist in future versions of Python. Other sections of this book should not be applied to classic classes.
Comment on this book here: discussion page. I appreciate feedback!
That’s all, folks!
Can Skim Section
This oddly placed section explains the type-instance and supertype-subtype relationships, and can be safely skipped if the reader is already familiar with these OO concepts. Skimming over the rules below might be useful though.
While we introduce many different objects, we only use two kinds of relationships (Figure 4.1, “Relationships”):
- is a kind of (solid line): Known to the OO folks as specialization, this relationship exists between two objects when one (the subclass) is a specialized version of the other (the superclass). A snake is a kind of reptile. It has all the traits of a reptile and some specific traits which identify a snake.Terms used: subclass of, superclass of and superclass-subclass.
- is an instance of (dashed line): Also known as instantiation, this relationship exists between two objects when one (the instance) is a concrete example of what the other specifies (the type). I have a pet snake named Squasher. Squasher is an instance of a snake.Terms used: instance of, type of, type-instance and class-instance.
Note that in plain English, the term ‘is a’ is used for both of the above relationships. Squasher is a snake and snake is a reptile are both correct. We, however, use specific terms from above to avoid any confusion.
We use the solid line for the first relationship because these objects are closer to each other than ones related by the second. To illustrate – if one is asked to list words similar to ‘snake’, one is likely to come up with ‘reptile’. However, when asked to list words similar to ‘Squasher’, one is unlikely to say ‘snake’.
It is useful at this point to note the following (independent) properties of relationships:
Dashed Arrow Up Rule
If X is an instance of A, and A is a subclass of B, then X is an instance of B as well.
Dashed Arrow Down Rule
If B is an instance of M, and A is a subclass of B, then A is an instance of M as well.
In other words, the head end of a dashed arrow can move up a solid arrow, and the tail end can move down (shown as 2a and 2b in Figure 4.2, “Transitivity of Relationships” respectively). These properties can be directly derived from the definition of the superclass-subclass relationship.
Applying Dashed Arrow Up Rule, we can derive the second statement from the first:
- Squasher is an instance of snake (or, the type of Squasher is snake).
- Squasher is an instance of reptile (or, the type of Squasher is reptile).
Earlier we said that an object has exactly one type. So how does Squasher have two? Note that although both statements are correct, one is more correct (and in fact subsumes the other). In other words:
Squasher.__class__
issnake
. (In Python, the__class__
attribute points to the type of an object).- Both
isinstance(Squasher, snake)
andisinstance(Squasher, reptile)
are true.
A similar rules exists for the superclass-subclass relationship.
Combine Solid Arrows Rule
If A is a subclass of B, and B is a subclass of C, then A is a subclass of C as well.
A snake is a kind of reptile, and a reptile is a kind of animal. Therefore a snake is a kind of animal. Or, in Pythonese:
snake.__bases__
is(reptile,)
. (The__bases__
attribute points to a tuple containing superclasses of an object).- Both
issubclass(snake, reptile)
andissubclass(snake, animal)
are true.
Note that it is possible for an object to have more than one base.
Leave a Reply