Python中的旧风格和新风格类有什么区别?

Python中的旧风格和新风格类有什么区别? 这些日子里是否有过使用旧式课程的理由?


从http://docs.python.org/2/reference/datamodel.html#new-style-and-classic-classes:

在Python 2.1之前,老式的类是用户唯一可用的风格。 (old-style)类的概念与type的概念无关:如果x是旧式类的实例,则x.__class__指定x的类,但type(x)始终是<type 'instance'> 。 这反映了一个事实,即所有旧式实例独立于它们的类,都使用一种称为实例的内置类型实现。

Python 2.2引入了新类,以统一类和类型的概念 。 新式类只是一种用户定义的类型,不多也不少。 如果x是新样式类的实例,则type(x)通常与x.__class__相同(尽管这不能保证 - 新样式的类实例被允许覆盖为x.__class__返回的值) 。

引入新式类的主要动机是提供一个完整的元模型的统一对象模型 。 它还具有许多直接的好处,例如能够对大多数内置类型进行子类化,或者引入可用于计算属性的“描述符”。

出于兼容性原因,类默认情况下仍然是旧式的 。 通过将另一个新样式类(即一个类型)指定为父类,或者如果不需要其他父类,则可以创建新样式类。 除了什么类型的返回之外,新风格类的行为与旧风格类的行为在许多重要细节中不同。 其中一些更改对于新对象模型来说很重要,就像特殊方法被调用的方式一样。 其他的是“修复”,在兼容性问题之前无法实现,比如多重继承情况下的方法解析顺序。

Python 3只有新风格的类 。 无论你是否从object继承类,Python 3都是新类。


宣言明智的:

新风格的类继承自对象或其他新风格的类。

class NewStyleClass(object):
    pass

class AnotherNewStyleClass(NewStyleClass):
    pass

旧式课堂不。

class OldStyleClass():
    pass

旧样式类和新样式类之间的重要行为变化

  • 超级补充
  • MRO改变(下面解释)
  • 描述符添加
  • 新的样式类对象不能被引发,除非派生自Exception (下面的例子)
  • __slots__添加
  • MRO(方法解决顺序)已更改

    在其他答案中提到过,但这里有一个经典MRO和C3 MRO(用于新风格类)之间区别的具体示例。

    问题是在多重继承中搜索属性(包括方法和成员变量)的顺序。

    经典类从左到右进行深度优先搜索。 第一场比赛停止。 他们没有__mro__属性。

    class C: i = 0
    class C1(C): pass
    class C2(C): i = 2
    class C12(C1, C2): pass
    class C21(C2, C1): pass
    
    assert C12().i == 0
    assert C21().i == 2
    
    try:
        C12.__mro__
    except AttributeError:
        pass
    else:
        assert False
    

    新式课堂 MRO在单个英语句子中更加复杂。 这里详细解释。 它的一个属性是一个基类只在其所有派生类都被搜索过后才被搜索。 它们具有显示搜索顺序的__mro__属性。

    class C(object): i = 0
    class C1(C): pass
    class C2(C): i = 2
    class C12(C1, C2): pass
    class C21(C2, C1): pass
    
    assert C12().i == 2
    assert C21().i == 2
    
    assert C12.__mro__ == (C12, C1, C2, C, object)
    assert C21.__mro__ == (C21, C2, C1, C, object)
    

    除非派生自Exception否则不能引发新样式类对象

    围绕Python 2.5可以提出很多类,在Python 2.6中被删除。 在Python 2.7.3上:

    # OK, old:
    class Old: pass
    try:
        raise Old()
    except Old:
        pass
    else:
        assert False
    
    # TypeError, new not derived from `Exception`.
    class New(object): pass
    try:
        raise New()
    except TypeError:
        pass
    else:
        assert False
    
    # OK, derived from `Exception`.
    class New(Exception): pass
    try:
        raise New()
    except New:
        pass
    else:
        assert False
    
    # `'str'` is a new style object, so you can't raise it:
    try:
        raise 'str'
    except TypeError:
        pass
    else:
        assert False
    
    链接地址: http://www.djcxy.com/p/1579.html

    上一篇: What is the difference between old style and new style classes in Python?

    下一篇: Why not inherit from List<T>?