python 中的 new-style 类及其实例详解 写在前面:br 刚刚接触python不久,对python中的Classic Class 及 New-Style Class 的区别很模糊 下文的95%来自Python In a Netshell第五章第二节,对一些已经过时的东西,我做了删减,对python2.4中新增的东西, 做了部分补充. 由于对python术语不是很熟悉,所以在此保留了原文,有翻译错误之处,还请大家指正.(有些地方直译很累,所以按照原来的意思用中文进行了重新组织) 注: Classic 被翻译为 传统, 如 Classic Class(传统类), classic object model (传统对象模型) New-Style 在视上下文被翻译为 新型, 如 New-Style Class(新型类),New-Style object model (新的对象模型)

5.2 New-Style Classes and Instances Most of what I have covered so far in this chapter also holds for the new-style object model introduced in Python 2.2. New-style classes and instances are first-class objects just like classic ones, both can have arbitrary attributes, you call a class to create an instance of the class, and so on. In this section, I'm going to cover the few differences between the new-style and classic object models. 5.2 新型类及其实例 前面我已经讲了python 2.2中引入的 new-style 对象模型. 新型类及其实例象传统类一样,都是第一层次对象,都可以拥有任意的属性,通过调用一个类生成该类的一个实例等等. 在这一小节,我来向大家揭示新的对象模型及传统对象模型的不同.

In Python 2.2 and 2.3, a class is new-style if it inherits from built-in type object directly or indirectly (i.e., if it subclasses any built-in type, such as list, dict, file, object, and so on). In Python 2.1 and earlier, a class cannot inherit from a built-in type, and built-in type object does not exist. In Section 5.4 later in this chapter, I cover other ways to make a class new-style, ways that you can use in Python 2.2 or later whether a class has superclasses or not. 从python2.2起,如果一个类继承自内建的object类型(或者它是任何内建类型如list,dict,file的子类),那它就是一个新型类。 在这之前,不允许通过继承内建类别生成新类,也根本没有object这个对象。在本章5.4节的后半部分,我介绍了将一个传统类改造成新型类的方法。

As I said at the beginning of this chapter, I suggest you get into the habit of using new-style classes when you program in Python 2.2 or later. The new-style object model has small but measurable advantages, and there are practically no compensating disadvantages. It's simpler just to stick to the new-style object model, rather than try to decide which model to use each time you code a new class. 在本章的开头,我建议每个人从现在开始养成只使用新型类的编程习惯(当然你得用Python2.2以上版本)。新的对象模型与传统对象模型相比有小但却很重要的优势,可以说接近完美. 很简单,认准新的对象模型,好好学没错.

5.2.1 The Built-in object Type As of Python 2.2, the built-in object type is the ancestor of all built-in types and new-style classes. The object type defines some special methods (as documented in Section 5.3 later in this chapter) that implement the default semantics of objects: 5.2.1 内建的object类型 objet类是所有内建类型及新型类的祖先。 object类定义了一系列特殊方法(本章5.3节后半部分有它们的文档)来实现所有对象的默认行为。 new , init You can create a direct instance of object, and such creation implicitly uses the static method new of type object to create the new instance, and then uses the new instance's init method to initialize the new instance. object.init ignores its arguments and performs no operation whatsoever, so you can pass arbitrary arguments to type object when you call it to create an instance of it: all such arguments will be ignored. new,init方法 你可以创建 object 的直接子类,静态方法 new()用来创建类的实例,实例的init()方法用来初始化自己。默认的init()方法会忽略你传递过来的任何参数。(2.4版好象做了改动,newinit方法默认都不接收任何参数,除非你重新实现这两个方法)

delattr , getattribute, setattr By default, an object handles attribute references as covered earlier in this chapter, using these methods of object. delattr , getattribute, setattr 方法 对象用这些方法来处理属性引用。本章前半部分已经做了详细介绍。

hash , repr, str An object can be passed to functions hash and repr and to type str. hash , repr, str 方法 一个对象可以作为参数传递给这些方法.

A subclass of object may override any of these methods and/or add others. object的子类可以重载这些方法,并且|或添加新的方法

5.2.2 Class-Level Methods The new-style object model allows two kinds of class-level methods that do not exist in the classic object model: static methods and class methods. Class-level methods exist only in Python 2.2 and later, but in these versions you can also have such methods in classic classes. This is the only feature of the new-style object model that is also fully functional with classic classes in Python 2.2 and later. 5.2.2了 类方法 新的对象模型提供了两种类方法(传统对象模型没有这些方法):静态方法和类方法。只有python2.2及更新版本才支持类方法. 需要提一下的是,在python2.2及更新版本中,传统类也实现了类方法。新的对象模型提供的诸多新特性中,有且仅有类方法这一特性被传统对象模型全功能实现。

5.2.2.1 Static methods A static method is a method that you can call on a class, or on any instance of the class, without the special behavior and constraints of ordinary methods, bound and unbound, on the first argument. A static method may have any signature: it may have no arguments, and the first argument, if any, plays no special role. You can think of a static method as an ordinary function that you're able to call normally, despite the fact that it happens to be bound to a class attribute. While it is never necessary to define static methods (you could always define a function instead), some programmers consider them to be an elegant alternative to such functions whose purpose is tightly bound to some specific class. 5.2.2.1静态方法 静态方法可以直接被类或类实例调用。它没有常规方法那样的特殊行为(绑定、非绑定、默认的第一个参数规则等等)。完全可以将静态方法当成一个用属性引用方式调用的普通函数来看待。任何时候定义静态方法都不是必须的(静态方法能实现的功能都可以通过定义一个普通函数来实现). 某些程序员认为,当有一堆函数仅仅为某一特定类编写时,这种方式可以提供使用上的一致性。 根据python2.4提供的新的语法,你可以象下面这样来创建一个静态方法,

class AClass(object):

anInstance = AClass( ) AClass.astatic( ) # prints: a static method anInstance.astatic( ) # prints: a static method 注:staticmethod是一个内建函数,用来将一个方法包装成静态方法,在2.4以前版本,要用下面的方式定义一个静态方法(不再推荐使用): class AClass(object):

这种方法在函数定义本身比较长时经常会忘记后面这一行.

5.2.2.2 Class methods A class method is a method that you can call on a class or on any instance of the class. Python binds the method's first argument to the class on which you call the method, or the class of the instance on which you call the method; it does not bind it to the instance, as for normal bound methods. There is no equivalent of unbound methods for class methods. The first formal argument of a class method is conventionally named cls. While it is never necessary to define class methods (you could always alternatively define a function that takes the class object as its first argument), some programmers consider them to be an elegant alternative to such functions. 一个类方法就是你可以通过类或它的实例来调用的方法, 不管你是用类调用这个方法还是类的实例调用这个方法,python只会将实际的类对象做为该方法的第一个参数.记住:方法的第一个参数都是类对象而不是实例对象. 按照惯例,类方法的第一个形参被命名为 cls. 任何时候定义类方法都不是必须的(静态方法能实现的功能都可以通过定义一个普通函数来实现,只要这个函数接受一个类对象做为参数就可以了).某些程序员认为这个特性当有一堆函数仅仅为某一特定类编写时会提供使用上的一致性.

You build a class method by calling built-in type classmethod and binding its result to a class attribute. Like all binding of class attributes, this is normally done in the body of the class, but you may also choose to perform it elsewhere. The only argument to classmethod is the function to invoke when Python calls the class method. Here's how to define and call a class method: 上面英文介绍的方法已经过时,根据python2.4提供的新特性,你可以象下面这样来生成一个类方法:

class ABase(object):

class ADeriv(ABase): pass bInstance = ABase( ) dInstance = ADeriv( ) ABase.aclassmet( ) # prints: a class method for ABase bInstance.aclassmet( ) # prints: a class method for ABase ADeriv.aclassmet( ) # prints: a class method for ADeriv dInstance.aclassmet( ) # prints: a class method for ADeriv 注:staticmethod是一个内建函数,用来将一个方法封装成类方法,在2.4以前版本,你只能用下面的方式定义一个类方法: class AClass(object):

并没有人要求必须封装后的方法名字必须与封装前一致,但建议你总是这样做(如果你使用python2.4版本以下时). 这种方法在函数定义本身比较长时经常会忘记后面这一行.

5.2.3 New-Style Classes All features of classic classes, covered earlier in this chapter, also apply to new-style classes. New-style classes also have some additional features with regard to the init special method, and they all have a new static method. 5.2.3 新型类 除了拥有传统类的全部特性之外,新型类当然还具有一些新特性.init特殊方法的行为与传统类相比有了一些变化,另外还新增了一个名为 new的静态方法

5.2.3.1 init A new-style class C that inherits init from object without overriding it lets you pass arbitrary arguments when you call C, but ignores all of those arguments. This behavior can be somewhat surprising. I suggest you override init in all new-style classes that directly subclass object, even in those rare cases in which your own class's init has no task to perform. For example: 5.2.3.1 init 新型类C中,从 object 继承来的原始 init方法,可以认为就是一个 pass 语句,因为它几乎什么都不做,建议你在所有的新型类中重载 init方法.

class C(object):

Now instantiating C( ) without arguments works, but mistakenly trying to pass an argument (e.g., C('xyz')) raises an exception. If class C did not override init, a call C('xyz') would silently ignore the erroneous argument. It's generally best not to silently ignore errors. 示例中的的类只允许无参数调用,硬要传递一个参数给它会产生异常(如用C('xyz')). 如果C没有重载init方法,调用C('xyz')会象'xyz'根本不存在一样忽略参数继续执行. 注意: (根据我的试验,2.4版中这点发生了变化,即使没有重载init方法,象C('xyz')这样调用一样会引发异常)

5.2.3.2 new Each new-style class has a static method named new. When you call C(*args,**kwds) to create a new instance of a new-style class C, Python invokes C.new(C,*args,**kwds). Python uses new's return value x as the newly created instance. Then, Python calls C.init(x,*args,**kwds), but only when x is indeed an instance of C (otherwise, x's state is as new had left it). Thus, for a new-style class C, the statement x=C(23) is equivalent to the following code: 5.2.3.2 new 每一个新型类都有一个名为new的静态方法. 当你调用 C(*args,**kwds)创建一个C实例时,python内部调用的是 C.new(C,*args,**kwds). new方法的返回值 x 就是该类的实例. 在确认 x 是C的实例以后, python调用C.init(x,*args,**kwds)来初始化这个实例. 也就是说,对新类C来讲,语句 x=C(23)等同于: x = C.new(C, 23) if isinstance(x, C): C.init(x, 23)

object.new creates a new, uninitialized instance of the class it receives as its first argument, and ignores any other arguments. When you override new within the class body, you do not need to add new=staticmethod(new), as you normally would: Python recognizes the name new and treats it specially in this context. In those rare cases in which you rebind C.new later, outside the body of class C, you do need to use C.new=staticmethod(whatever). object.new创建一个新的,未初始化的类实例,它接收传递过来的第一个参数(也就是类对象本身),忽略其它的参数.当你重载new方法时,你不必使用函数修饰符@staticmethod, python解释器根据上下文会认出new()方法是一个静态方法. 如果你需要重绑定 C.new方法,你只需要在类外面执行 C.new=staticmethod(你想使用的新方法)就可以了.(极少有这样的需求)

new has most of the flexibility of a factory function, as covered earlier in this chapter. new may choose to return an existing instance or to make a new one, as appropriate. When new does need to create a new instance, it most often delegates creation by calling object.new or the new method of another built-in type that is a superclass of C. The following example shows how to override static method new in order to implement a version of the Singleton design pattern: new方法拥有函数工厂的绝大部分弹性. 根据实际需求,我们可以让new返回一个已有的实例或者创建一个新的实例. 下面举一个通过重载new方法实现独身对象的设计模式的例子:

class Singleton(object):

Any subclass of Singleton (that does not further override new) has exactly one instance. If the subclass defines an init method, the subclass must ensure its init is safe when called repeatedly (at each creation request) on the one and only class instance. Singleton的所有子类(当然是没有重载new方法的子类)都只可能有一个实例. 如果该类的子类定义了一个init方法,那么它必须保证它的init方法能够安全的对同一实例进行多次调用.

5.2.4 New-Style Instances All features of instances of classic classes, covered earlier in this chapter, also apply to instances of new-style classes. In addition, new-style classes may define attributes called properties and a special attribute named slots that affects access to instance attributes. The new-style object model also adds a special method getattribute that is more general than the getattr special method present in both the classic and new-style object models. It also has different semantics for per-instance definition of special methods. 5.2.4新型类实例 新型类实例除了拥有传统类实例的全部特性之外,还拥有一种称为property的新属性及一个叫作slots的特殊属性,该属性会对实例其它属性的访问产生重要影响. 新的对象模型同样添加了一个新的方法 getattribute 比原有的 getattr 方法更通用. 不同的实例可以拥有这些特殊方法的不同实现.

5.2.4.1 Properties A property is an instance attribute with special functionality. You reference, bind, or unbind the attribute with the normal syntax (e.g., print x.prop, x.prop=23, del x.prop).

print x.prop x.prop=23 del x.pro However, rather than following the usual semantics for attribute reference, binding, and unbinding, these accesses call methods on instance x that you specify when defining the property using the built-in type property. Here's how to define a read-only property: 然而,property如果只有这点功能那就和普通属性没什么两样了,property有它的独到之处,请往下读. 下面介绍如何定义一个只读property class Rectangle(object):

Each instance r of class Rectangle has a synthetic read-only attribute r.area, computed on the fly in method r.getArea( ) by multiplying the sides of the rectangle. The docstring Rectangle.area.doc is 'area of the rectangle'. The property is read-only (attempts to rebind or unbind it fail) because we only specify a get method in the call to property. 矩形类的每一个实例 r 均拥有一个只读属性 r.area ,该属性由 r.getArea()方法实时计算得来. Rectangle.area.doc是'area of the rectangle',这个属性是只读的(试图对它进行重绑定或解除绑定的企图都注定会失败),这是因为我们在property定义中只指定了该属性 get 方法.

Properties perform tasks that are similar to those of special methods getattr, setattr, and delattr (covered in Section 5.3 later in this chapter), but in a faster and simpler way. You build a property by calling built-in type property and binding its result to a class attribute. Like all binding of class attributes, this is normally done in the body of the class, but you may also choose to perform it elsewhere. Within the body of a class C, use the following syntax: properties 干的活与那些特殊方法getattr,setattr,delattr等是极其相似的,不过同样的活它干起来更简单更快捷. 内建property类别(我倒宁愿把当成一个函数来看)用来生成一个property,并将其返回值绑定为一个类属性.如同绑定类的常规属性,一般在定义类时就创建property,当然也有其它选择.假设在定义新型类 C 时,使用以下语法: 13126665427 13810555150 attrib = property(fget=None, fset=None, fdel=None, doc=None)

When x is an instance of C and you reference x.attrib, Python calls on x the method you passed as argument fget to the property constructor, without arguments. When you assign x.attrib = value, Python calls the method you passed as argument fset, with value as the only argument. When you perform del x.attrib, Python calls the method you passed as argument fdel, without arguments. Python uses the argument you passed as doc as the docstring of the attribute. All arguments to property are optional. When an argument is missing, the corresponding operation is forbidden. For example, in the Rectangle example, we made property area read-only, because we passed only argument fget, not arguments fset and fdel. x是C的一个实例,当你引用 x.attrib 时,python调用 fget方法取值给你. 当你为x.attrib赋值: x.attrib=value 时,python调用 fset方法,并且value值做为fset方法的参数,当你执行del x.attrib 时,python调用fdel方法,你传过去的名为doc的参数即为该属性的文档字符串. 在矩形类中,因为我们没有为area属性指定fset和fdel参数,所以该属性只能读取.

5.2.4.2 slots Normally, each instance object x of any class C has a dictionary x.dict that Python uses to let you bind arbitrary attributes on x. To save some memory (at the cost of letting x have only a predefined set of attribute names), you can define in class C a class attribute named slots, which is a sequence (normally a tuple) of strings (normally identifiers).When class C has an attribute slots, a direct instance x of class C has no x.dict, and any attempt to bind on x any attribute whose name is not in C.slots raises an exception. Using slots lets you reduce memory consumption for small instance objects that can do without the ability to have arbitrarily named attributes. Note that slots is worth adding only to classes that can have so many instances that saving a few tens of bytes per instance is important. Typically classes that can have millions, not mere thousands, of instances alive at the same time. Unlike most other class attributes, slots works as I've just described only if some statement in the class body binds it as a class attribute. Any later alteration, rebinding, or unbinding of slots has no effect, nor does inheriting slots from a base class. Here's how to add slots to the Rectangle class defined earlier, to get smaller (though less flexible) instances: 5.2.4.2 slots属性 通常,每个实例对象 x 都拥有一个字典 x.dict. python通过此字典允许你绑定任意属性给 x 实例. 定义一个名为slots的类属性可以有效减少每个实例占用的内存数量.slots是一个字符串序列(通常是一个tuple). 当类 C 拥有 slots属性, x的直接子类就没有 x.dict属性. 如果试图绑定一个slots中不存在属性给实例的话,就会引发异常. slots属性虽然令你失去绑定任意属性的方便,却能有效节省每个实例的内存消耗,有助于生成小而精干的实例对象. 注: 当一个类会生成很多很多实例时(有些类同时拥有数百万而不是几千个实例),即使一个实例节省几十个字节都可节省一大笔内存时,就值得使用slots属性.只有在类定义中可以使用 slots=aTuple 语句来为一个类添加slots属性,其它任何位置对一个类或其父类的slots属性的修改,重新绑定或解除绑定都是无效的. 下面介绍如何通过添加 slots属性给刚才定义的 Rectangle 类,以得到瘦身的类实例:

class OptimizedRectangle(Rectangle):

We do not need to define a slot for the area property. slots does not constrain properties, only ordinary instance attributes.The attributes that would reside in the instance's dict if slots wasn't defined. slots里不能包含 properties, 只能包含常规实例属性.我们不需也不允许给area property也定义一个slot. 若不定义 slots属性,常规属性则保存在实例的dict属性中.

5.2.4.3 getattribute All references to instance attributes for new-style instances proceed through special method getattribute. This method is supplied by base class object, where it implements all the details of object attribute reference semantics as documented earlier in this chapter. However, you may override getattribute for special purposes, such as hiding inherited class attributes (e.g., methods) for your subclass's instances. The following example shows one way to implement a list without append in the new-style object model: 5.2.4.3 getattribute 对新型类的实例来说, 所有的属性引用都是通过特殊方法getattribute()完成的.该方法由基类对象提供,负责实现对象属性引用的全部细节.在本章的前面有该方法详细的文档. 如果有特殊需求,你也可以重载 getattribute属性(比如你打算在子类实例中隐藏父类的某些属性或方法).下面的例子演示了实现一个没有append方法的list类:

class listNoAppend(list):

An instance x of class listNoAppend is almost indistinguishable from a built-in list object, except that performance is substantially worse, and any reference to x.append raises an exception. 除了功能不全以外,该类的实例与内建list对象完全相同.任何调用该类实例append方法的企图都会引发一个异常.

5.2.4.4 Per-instance methods Both the classic and new-style object models allow an instance to have instance-specific bindings for all attributes, including callable attributes (methods). For a method, just like for any other attribute, an instance-specific binding hides a class-level binding: attribute lookup does not even look at the class if it finds a binding directly in the instance. In both object models, an instance-specific binding for a callable attribute does not perform any of the transformations detailed in Section 5.1.5 earlier in this chapter. In other words, the attribute reference returns exactly the same callable object that was earlier bound directly to the instance attribute. 5.2.4.4个体实例方法 传统与新的对象模型都允许一个实例拥有私有的属性和方法(通过绑定或重绑定) . 实例的私有属性会屏蔽掉类定义中的同名属性.举例来说: class abc(object):

b=abc() def afunc():

b.attrib_a=afunc b.attrib_a()

该例子将打印 'hello,world!'

Classic and new-style object models do differ on per-instance binding of the special methods that Python invokes implicitly as a result of various operations, as covered in Section 5.3 later in this chapter. In the classic object model, an instance may usefully override a special method, and Python uses the per-instance binding even when invoking the method implicitly. In the new-style object model, implicit use of special methods always relies on the class-level binding of the special method, if any. The following code shows this difference between classic and new-style object models: 在python隐式调用实例的私有(后绑定)特殊方法时,新的对象模型改变了传统对象模型的行为.在传统对象模型中,无论是显示调用,还是隐式调用,都会调用这个实例的后绑定特殊方法.而在新的对象模型中,除非显示调用实例的特殊方法,否则python总是去调用在类中定义的特殊方法.下面这个例子可以说明这一点:

def fakeGetItem(idx): return idx class Classic: pass c = Classic( ) c.getitem = fakeGetItem print c[23] # prints: 23 class NewStyle(object): pass n = NewStyle( ) n.getitem = fakeGetItem print n[23] # 程序执行到这步会出错. 如果将代码改为 print n.getitem(23) 则正常运行 # Traceback (most recent call last): # File "<stdin>", line 1, in ? # TypeError: unindexable object

The semantics of the classic object model in this regard are sometimes handy for tricky and somewhat obscure purposes. However, the new-style object model's approach regularizes and simplifies the relationship between classes and metaclasses, covered in Section 5.4 later in this chapter. 调用n[23],将产生一个隐式的getitem方法调用,因为新型类 n 中并未定义该方法,所以引发了异常.不过如果你使用n.getitem(23)这种方式来显式调用特殊方法时,它还是可以工作的.

5.2.5 Inheritance in the New-Style Object Model In the new-style object model, inheritance works similarly to the way it works in the classic object model. One key difference is that a new-style class can inherit from a built-in type. The new-style object model, like the classic one, supports multiple inheritance. However, a class may directly or indirectly subclass multiple built-in types only if those types are specifically designed to allow this level of mutual compatibility. Python does not support unconstrained inheritance from multiple arbitrary built-in types. Normally, a new-style class only subclasses at most one substantial built-in type; this means at most one built-in type in addition to object, which is the superclass of all built-in types and new-style classes and imposes no constraints on multiple inheritance. 5.2.5 新的对象模型中的继承 在新的对象模型中,继承的使用方式与传统模型大致相同.一个关键的区别就是新型类能从一个内建类型中继承而传统类不能. 新型类仍然支持多继承,若要从多个内建类型继承生成一个新类,则这些内建类型必须是经过特殊设计能够相互兼容. python不支持随意的从多个内建类型进行多继承,通常情况都是通过至多从一个内建类型继承得到新类.这意味着在多继承时,除object以外,至多有一个内建类型可以是其它内建类型和新型类的超类.

5.2.5.1 Method resolution order In the classic object model, method and attribute lookup (also called resolution order) among direct and indirect base classes proceeds left-first, depth-first. While very simple, this rule may produce undesired results when multiple base classes inherit from the same common base class and override different subsets of the common base class's methods; in this case, the overrides of the rightmost base class are hidden in the lookup. For example, if A subclasses B and C in that order, and B and C each subclass D, the classic lookup proceeds in the conceptual order A, B, D, C, D. Since Python looks up D before C, any method defined in class D, even if class C overrides it, is therefore found only in the base class D version. This issue causes few practical problems only because such an inheritance pattern, also known as a diamond-shaped inheritance graph, is rarely used in the classic Python object model. 5.2.5.1方法解析顺序: 在传统对象模型中,方法和属性按 从左至右 深度优先 的顺序查找.显然,当多个父类继承自同一个基类时,这会产生我们不想要的结果. 举例来说, A是B和C的子类,而B和C继承自D,传统对象模型的的属性查找方法是 A-B-D-C-D. 由于Python先查找D后查找C,即使C对D中的方法进行了重定义,也只能使用D中定义的版本.由于这个继承模式固有的问题,在实际应用中会造成一些麻烦.

In the new-style object model, however, all types directly or indirectly subclass object. Therefore, any multiple inheritance gives diamond-shaped inheritance graphs, and the classic resolution order would often produce problems. Python's new-style object model changes the resolution order by leaving in the lookup sequence only the rightmost occurrence of any given class. Using the example from the previous paragraph, when class D is new-style (e.g., D directly subclasses object), the resolution order for class A becomes A, B, C, D, object, and no anomalies arise. 在新的对象模型中,所有类均直接或间生成子类对象. python改变了传统对象模型中的解析顺序,使用上面的例子,当D是一个新型类(比如D是object 的直接子类),新的对象模型的搜索顺序就变为 A-B-C-D.

Each new-style class and built-in type has a special read-only class attribute called mro, which is the tuple of types used for method resolution, in order. You can reference mro only on classes, not on instances, and, since mro is a read-only attribute, you cannot rebind or unbind it. 每个内建类型及新型类均内建一个特殊的只读属性 mro ,这是一个tuple,保存着方法解析类型. 只允许通过类来引用 mro(不允许通过实例).

5.2.5.2 Cooperative superclass method calling As we saw earlier in this chapter, when a subclass overrides a method, the overriding method often wants to delegate part of its operation to the superclass's implementation of the same method. The simple solution that is idiomatic in Python's classic object model (calling the superclass's version directly with unbound method syntax) is imperfect in cases of multiple inheritance with diamond-shaped graphs. Consider the following definitions: 5.2.5.2 协作式调用超类方法 前面我们提到,当一个子类重载了父类中一个方法,子类中的方法通常要调用父类中的同名方法来做一些事.这也是python传统对象模型惯用的方式,即使用非绑定方法语法调用父类的同名方法.当多继承时,这种方法是有缺限的,见下例: class A(object):

class B(A):

class C(A):

class D(B,C):

In this code, when we call D( ).met( ), A.met ends up being called twice. How can we ensure that each ancestor's implementation of the method is called once, and only once? This problem turns out to be rather hard to solve without some special help. The special help that Python 2.2 provides is the new built-in type super. super(aclass, obj) returns a special superobject of object obj. When we look up an attribute (e.g., a method) in this superobject, the lookup begins after class aclass in obj's method resolution order. We can therefore rewrite the previous code as: 在上面的代码中,当我们调用 D().met()方法时, A.met()方法被调用了两次. 我们怎样才可以保证每个父类的实现均被顺序调用且仅仅调用一次呢?不采取点特殊措施这个问题很难解决.从python2.2起,提供了这样一个特殊手段. 那就是 super类型. super(aclass,obj)返回对象obj的一个特殊的超对象(superobject). 当我们调用该超对象的一个属性或方法时,就保证了每个父类的实现均被调用且仅仅调用一次了. 改写后的代码如下:

class A(object):

class B(A):

class C(A):

class D(B,C):

Now, D( ).met( ) results in exactly one call to each class's version of met. If you get into the habit of always coding superclass calls with super, your classes will fit smoothly even in complicated inheritance structures. There are no ill effects whatsoever if the inheritance structure turns out to be simple instead (as long as your code only runs on Python 2.2 and later, of course). 现在就可以得到期望的结果了. 如果你养成了总是使用superclass调用父类方法,你的类就能适应无论多复杂的继承结构.