标签:des style blog http io color os ar 使用
译文:http://wiki.woodpecker.org.cn/moin/PyTypesAndObjects
原文:http://www.cafepy.com/article/python_attributes_and_methods/
解释新式的Python对象(new-style):
<type ‘type‘> and <type ‘object‘>是什么东西
新 式类型New-style包含在Python2.2及以上,包括3.x。这些版本之间会有细微差异,不过这里涉及到的概念都是无差别的。本书讲的内容通常 被称作Python类型系统或Python对象模型Python type system, or the object model.
This revision: 1.24
Author: shalabh@cafepy.com
应该注意的一些:
python之旅快乐?Happy pythoneering!
怎样准确的表达python中object的含义呢? 系统中每个对象是一条规则 - 是一个实体的体现. 可以通过如下特征来确定一个对象:
==== type 和 bases === (如果存在的话) 很重要,因为它们定义了对象和其他对象之间的特定关系. 请记住对象的types 和 bases只是另外一些对象.很快就会看到这一点.
你可能会想到对象有名字但名字不是对象的一部分. 对象名在对象之外的命名空间中存在(比如函数的本地变量) 或者作为另一个对象的属性.
即使对2这样一个简单对象所包含的东西也比我们眼睛看到的要多.
Example1.1. 查看integer对象
>>> two = 2 1 >>> type(two) <type ‘int‘> 2 >>> type(type(two)) <type ‘type‘> 3 >>> type(two).__bases__ (<type ‘object‘>,) 4 >>> dir(two) 5 [‘__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‘]
2 <type ‘int‘>. 这是另一个对象, 现在来解剖一下. 注意这个对象也被称为 int 而 <type ‘int‘> 只是它打印出来的样子.
3 <type ‘int‘> 的type是另外一个叫做 <type ‘type‘>的对象象.
4 <type ‘int‘> 的bases属性是一个tuple,这个tuple包含一个叫 <type ‘object‘>的对象. 我想你没考虑过检查 bases这个属性 ;).
耐心点先来看我们的第一条规则
int 是 object. 这不是说例如2和77这样的数字是object (他们确实是), 而是说确实有另外一个对象叫做 int ,他处于内存中的实际的整数之外的内存中. 实际上所有的整数对象的class属性都指向 int,他们共同的心声是"知我者int也". 在一个object上调用type()方法返回的也正好是这个对象的class属性的值.
我们定义的所有classes都是对象, 当然这些classes的实例也是对象.甚至我们定义的方法和函数也是对象. 并且像我们看到的,这些对象都有些不同.
现在我们来从头构建python的对象系统. 我们从一个空白状态开始。第一个框中的对象产生第二个框的对象,第二个框的对象产生第三个框的对象。
然后每个框中的对象有继承关系。即横向是实例化,纵向是继承
Figure 1.1. 空白状态
你可能在想为啥有两天灰色的竖线. 后面慢慢来揭晓. 竖线是来区别不同的区域的. 这个空白图中, 我们来逐渐加上各种对象,画上他们之间的关系,慢慢画满.
这个有助于帮助我们暂且搁置先入为主的各种有关面向对象的类和对象的观念,以对象的方式(我们这里的对象)来理解一切。
我们使用两种关系就可以连接我们所引入的这许多不同的对象. 这两种关系是子类-父类关系 (也可叫做特别化或继承, 如"人是个动物", 等等.) 和类-实例关系 (也叫实例化, 比如"Joe是个人", 等等.)。
如果你对这些概念已经熟悉了,可以继续往下看了,否则的话你可能需要先去看看这一部分“面向对象”.
我们来查看<type ‘object‘> 和 <type ‘type‘>这两个对象.
Example 2.1. Examining <type ‘object‘> and <type ‘type‘>
>>> object 1 <type ‘object‘> >>> type 2 <type ‘type‘> >>> type(object) 3 <type ‘type‘> >>> object.__class__ 4 <type ‘type‘> >>> object.__bases__ 5 () >>> type.__class__ 6 <type ‘type‘> >>> type.__bases__ 7 (<type ‘object‘>,)
1 2 这是python中两个最基本对象. 前面我们介绍过用type()来查看一个对象object的类型type(通常就是class属性的值). 其实,它本身是个对象,并且也是个查看其他对象类型的方式
3 4 5 查看 <type ‘object‘>: <type ‘object‘>的类型type是<type ‘type‘>. 我们也验证了它的class属性确实和调用type()是一样的.
6 7 查看 <type ‘type‘>: 有趣的是<type ‘type‘>的type是它自己! 它的bases属性包含了 <type ‘object‘>.
下面我们来画一下所看到的.
Figure 2.1. 鸡和蛋的关系
图中两个对象是python最基本对象. 也可以一次介绍一个,但这里有个鸡和蛋一样的矛盾 - 先介绍哪个好? 这两个对象是互相依赖的 - 每一个本身都不能单独存在,都要借助对方来描述自己.
还是继续我们的python实验吧:
Example 2.2. 关于 <type ‘object‘> 和 <type ‘type‘>的更多内容
>>> isinstance(object, object) 1 True >>> isinstance(type, object) 2 True
1 看看发生了什么? 这是 Dashed Arrow Up Rule 的一个应用. 由于<type ‘type‘> 是 <type ‘object‘>的子类, 则<type ‘type‘> 的实例也是<type ‘object‘>的实例.
如果对上面的证明不太理解, 没关系 - 反正也没什么用.
再看一个新概念 - 类对象type objects. 我们介绍过的对象都是类对象. 所说的类对象是什么呢? 类对象有如下共同特点:
它们可以被实例化. 意味着你可以新建一个已存在对象的实例. 这个新对象的class属性就是已存在对象.
任何类对象的类型是 <type ‘type‘>.
是 的. Types和classes在Python中确实是同一个东西 (免责声明: 对老式类和早于2.2版本的Python不适用. 那是 types和classes有些不同但那时很久前的事了,现在已这些不同点已经一致了。因此让过去的事就过去吧,不好吗?). 不要吃惊,使用type()函数和class属性得到的是一样的.
class 这个术语传统是指被class这个关键字创建的class. 内置类型 (比如int和string)通常不和classes联系起来, 这更多是约定俗成的,实际上types和classes是同一个东西.我觉得这点很重要,可以提出一个规则:
type和class这两个术语在所有Python >= 2.3的版本中是一样的.
类 对象Types 和 (嗯,,让我想个更好的词) 非类对象non-types (呵呵!) 都是对象 但只有types可以子类化. Non-types代表的是具体的值所以子类化并没有意义. 非类对象的两个例子是整数 2 以及字符串 "hello". 想想,2的子类是什么意思,没意思吧?
还对判断类对象和非类对象感觉混淆吗?有一个简单的规则:
如果一个对象是<type ‘type‘>的实例, 那它就是类对象. 否则是非类对象.
回头看,可以证明这个规则对我们所碰到的所有对象都是成立的, 包括 <type ‘type‘>,它是自己的实例.
总结一下:
<type ‘object‘> 是 <type ‘type‘>的一个实例.
<type ‘object‘> 不是任何类的子类.
<type ‘type‘> 是自己的实例.
<type ‘type‘> 是 <type ‘object‘>的子类.
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中不止这两个对象,这两个基本对象有一堆的兄弟
Figure 2.2. 一些内置类型
上面展示了一些内置对象,下面解释一下.
Example 2.3. 查看一些内置类型
>>> list 1 <type ‘list‘> >>> list.__class__ 2 <type ‘type‘> >>> list.__bases__ 3 (<type ‘object‘>,) >>> tuple.__class__, tuple.__bases__ 4 (<type ‘type‘>, (<type ‘object‘>,)) >>> dict.__class__, dict.__bases__ 5 (<type ‘type‘>, (<type ‘object‘>,)) >>> >>> mylist = [1,2,3] 6 >>> mylist.__class__ 7 <type ‘list‘>
1 内置的<type ‘list‘> 对象.
2 <type ‘list‘>的类型是<type ‘type‘>.
3 它有一个基类 (即 superclass), <type ‘object‘>.
4 5 类似的还有 <type ‘tuple‘> 和 <type ‘dict‘>.
6 创建<type ‘list‘>的实例的方法.
7 一个list对象的type是 <type ‘list>. 不要惊讶.
当创建一个tuple或dictionary对象时, 他们是各自对应类型的实例.
怎样创建一个mylist的实例呢? 不能. 因为 mylist对象不是一个type.
内置对象是内置在python中的. 当我们启动python的时候就存在,通常程序结束的时候他们还存在.那我们怎样创建新对象呢?
新对象不会无中生有的出现. 它们必须通过现有的对象来创建.
Example 2.4. 通过子类化构建对象
# Python 2.x: class C(object): 1 pass # Python 3.x, 确定的object基类已经不需要指定了, 默认创建的都是class的基类: class C: 2 pass class D(object): pass class E(C, D): 3 pass class MyList(list): 4 pass
从上面的例子可知, C.bases 包含 <type ‘object‘>, 而 MyList.bases 包含 <type ‘list‘>.
子类化只是产生对象的一种方式,还有另外一种.
Example 2.5. 通过实例化构建对象
obj = object() 1 cobj = C() 2 mylist = [1,2,3] 3
2 对某些内置类型python有特殊的语法来创建新对象. 方括号创建 <type ‘list‘>的实例; 整形数字直接量创建一个 <type ‘int‘>对象.
有了上面练习的这些, 我们的对象图就看起来更完美了.
Figure 2.3. 用户定义对象
注意,仅仅通过子类化 <type ‘object‘>, 类型C 自动成为 <type ‘type‘>的实例. 可以通过查看C.class来确认这一点. 下节再对此做解释.
对于这一点你可能会冒出下面这些问题,也可能没有,不过我还是打算解答一下:
A: python内部,当创建对象时, 肯定会使用一个type来创建这个type对象的一个实例. 具体的情况是调用这个类对象的new() 和 init() 方法(对这些内容的讨论已操作本书范围). 某种意义上,可以将类对象(type)看做是能够生产新对象的工厂. 这些生产出来的对象的类型(type)将是创建他们的类对象(type). 这就是为什么每个对象都有个类型type的原因.
A: 这要看你子类化时指定的基类,将基类的类型type作为新对象(新类)的type,在 Example 2.4, “通过子类化构建对象”这个例子中 , <type ‘type‘> (指定的基类<type ‘object‘>的type) 被用做正在创建的C的类型.
想一下就会知道多数iqngk下, <type ‘object‘>的任何子类 (以及子类的子类,等等)都将被赋予<type ‘type‘>这个类型.
A: 是的,一个可选方案就是用 metaclass 这个类的属性,如下示例:
Example 2.6. 使用class关键字定义类时指定一个type对象
class MyCWithSpecialType(object): __metaclass__ = SpecialType
这样Python在创建MyCWithSpecialType时,是实例化 SpecialType的, 而不是<type ‘type‘>.
Q: 太棒了,可以把任意type对象作为metaclass?
A: 不是的,指定的元类metaclass必须是所用的基类的type的子类No. It must be a subclass of the type of the base object. 比如上面的例子中:
MyCWithSpecialType 的基类是<type ‘object‘>.
<type ‘object‘>的 type是<type ‘type‘>.
所以如果用SpecialType做 metaclass的话, SpecialType必须是 <type ‘type‘>的子类才行.
使用像SpecialType这样的东西需要特别小心,这些已经超出本书的范围.
(译注,
似乎不是很确切,下面这个例子能运行。当然,我们不建议这么样,因为BClass的__metaclass__并不是AClass的元类的子类,
这就违反了__metaclass__的规则,你并不能确定BClass用的是自己定义的__metaclass__=type作元类,用查看BClass.__class__
,显示Atype。 class Atype(type): pass class AClass(object): __metaclass__ = Atype class BClass(AClass): __metaclass__ = type
Q: 如果有多个基类,但没指定metaclass,会使用哪个type对象呢?
A: 好问题. 取决于python能否计算出用哪个。若所以基类有相同的type, 就是用这个. 若他们有不同的互不相干的type, python无法算出用哪个. 此时就需要指定一个metaclass, 并且这个metaclass 必须是每个基类的type的共同子类.
Q: 我什么时候应该用metaclass?
A: 永远别用 (只要你还问这个问题的话就别用
最后一章,我们最终得到一个有各种不同python对象的图
Figure 3.1. Python对象图
这一节我们也将解释图中灰色的竖线是干啥的. 根据人们对不同对象的叫法,灰色竖线将对象图分成三个区域 - 元类,类和实例.
虚线穿过了区域边界 (比如,从对象到元对象). 唯一的特例是<type ‘type‘> (也只能这样了, 否则就需要在它的左边再分一个另一个区域,另一个区域左边还得一个区域等等无穷尽。因为type的type就是自己啊).
实线不穿过边界. 又有一个例外, <type ‘type‘> -> <type ‘object‘> .
如果通过子类化<type ‘type‘>创建一个对象,它应该放在最左边的区域。并且它既是<type ‘type‘>的实例也是<type ‘type‘>的子类。
Also note that <type ‘type‘> is indeed a type of all types, and <type ‘object‘> a superclass of all types (except itself).
也要记住,<type ‘type‘>确实是所有类对象的type,而<type ‘object‘> 是所有类对象的超类(除了它自己)。
总结一下谈到过的内容:
<type ‘type‘>;<type ‘object‘> 是python系统中的两个基本对象.
每个对象都有class,并且等于该对象的type.
每个type object有bases属性, 指向该对象的超类.只有<type ‘object‘>的bases是空的.
某些non-type objects可以用特定的python语法创建.比如[1, 2, 3] 创建一个 <type ‘list‘>的实例.
B在A.bases中,
对于A.bases中的每一个Z,如果 issubclass(Z,B)为True.(即若A的每个直接基类都是B的子类的话,就可以推导出 A也是B的子类)
BBA.class,
issubclass(A.class,B) 为True.(即若A的类型是B的子类的话,A也就是B的实例)
Example 3.1. 更多内置 types
>>> import types 1 >>> types.ListType is list 2 True >>> def f(): 3 ... pass ... >>> f.__class__ is types.FunctionType 4 True >>> >>> class MyList(list): 5 ... pass ... >>> class MyFunction(types.FunctionType): 6 ... pass ... Traceback (most recent call last): File "<stdin>", line 1, in ? TypeError: type ‘function‘ is not an acceptable base type >>> dir(types) 7 [‘BooleanType‘, ‘DictProxyType‘, ‘DictType‘, ..]
4 function对象的类型是 types.FunctionType
我们可以用我们选择的对象间的关系来创建新对象,但这对我们有什么用?
python中的属性访问机制在本系列的第二本书中讲解:Python Attributes and Methods.
这是一份关于python中的classic classes 的备忘录. 用一个空的class关键字可以创建老式(早于python2.2)的类.
>>> class ClassicClass: 1 ... pass ... >>> type(ClassicClass) 2 <type ‘classobj‘> >>> import types >>> types.ClassType is type(ClassicClass) 3 True >>> types.ClassType.__class__ 4 <type ‘type‘> >>> types.ClassType.__bases__ 5 (<type ‘object‘>,)
3 老式类的类型是一个叫types.ClassType 的对象.
types.ClassType这个对象某种程度上可替代<type ‘type‘>. 该对象的实例(即老式类) 该对象的实例 (老式类) 也是类对象types. 新老式对象之间的属性访问规则是不同的。 types.ClassType 这个对象的存在时为了向后兼容,在将来版本的python中可能就没有了. 本书的其他部分所讲的内容不应被套用到老式类上去。去。
请在这里评论: discussion page. 感谢反馈!
到处结束了,朋友们!
可以略过的章节?Can Skim Section
用古怪的一节来讲解 类型-实例 和 超类-子类关系
我们引入很多不同的对象,他们之间只用两种关系就可以概括 ( 4.1. 关系)
术语: *的子类, *的超类 and 超类-子类.
术语: *的实例, *的类型, 类型-实例 或 类-实例.
注意在简单英语中术语,以上两种关系都可以叫‘是一个‘ . , 蛇是一个爬虫. 不过我们用特定的术语来避免混淆.
Figure 4.1. 关系
换句话说, 虚线箭头一端可以向上移到实线箭头,虚线箭尾可以向下移 ( 如Figure 4.2. ""关系的传递" 中的2a和2b各自表示的).这些性质可以直接从父类-子类的关系定义得到
Figure 4.2. 关系的传递
应用 虚线向上规则, 可以从下面第一条描述得到第二条:
之前我们说过每个对象有一个确切的类型.为啥 Squasher有两个? 注意虽然每个说法都是正确的, 其中一个更确切 (确切的说可以归纳另一个).也可以说:
Squasher.class 是 snake. (Python中, 对象的class指向对象的type).
父类-子类关系也有个类似的规则.
蛇是一种爬虫, 爬虫是一种动物. 所有蛇也是一种动物. 或者用Python代码表示:
snake.bases 是 (reptile,). (对象的bases 属性是一个包含对象超类的元组).
注意对象可能有不止一个基类.
[descrintro] Unifying types and classes in Python 2.2 Guido van Rossum.
[pep-253] Subclassing Built-in Types Guido van Rossum.
This book was written in DocBook XML. The HTML version was produced using DocBook XSL stylesheets and xsltproc. The PDF version was produced using htmldoc. The diagrams were drawn using OmniGraffe [1]. The process was automated using Paver [2].
标签:des style blog http io color os ar 使用
原文地址:http://www.cnblogs.com/ajianbeyourself/p/4055331.html