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'> 。 这反映了这样一个事实:所有旧式实例独立于它们的类,都使用一个名为instance的内置types实现。

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

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

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

Python 3只有新风格的类 。 无论你是否从子类inheritance,类都是Python 3中的新类。

宣言明智的:

新风格的类inheritance自对象,或从另一个新风格的类inheritance。

 class NewStyleClass(object): pass class AnotherNewStyleClass(NewStyleClass): pass 

老式的课程不。

 class OldStyleClass(): pass 

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

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

MRO(方法解决顺序)已更改

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

问题是在多重inheritance中search属性(包括方法和成员variables)的顺序。

经典类从左到右进行深度优先search。 第一场比赛停止。 他们没有__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更加复杂。 这里详细解释。 它的一个属性是一个基类只有一次search到所有的派生类。 他们有显示search顺序的__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 

对于属性查找,旧式类仍然稍微快一些。 这通常不重要,但在对性能敏感的Python 2.x代码中可能会有用:

在[3]中:A类:
    ...:def __init __(self):
    ...:self.a ='你好'
    ...: 

在[4]中:class B(object):
    ...:def __init __(self):
    ...:self.a ='你好'
    ...: 

在[6]中:aobj = A()
在[7]中:bobj = B()

在[8]中:%timeit aobj.a
 10000000个循环,最好3个:每个循环78.7纳秒

在[10]中:%timeit bobj.a
 10000000个循环,最好是每个循环86.9 ns

Guido写了New Style Class的“Inside Story” ,这是一篇关于Python中新式和旧式类的非常棒的文章。

Python 3只有新式的类,即使你写了一个“旧式类”,它也是隐含地从object派生的。

新式class级有一些老式class级缺乏的先进特征,比如super新型C3 mro ,一些神奇的方法等等。

这是一个非常实用,真实/错误的区别。 以下代码的两个版本之间的唯一区别是在第二个版本Person从对象inheritance。 除此之外,两个版本是相同的,但结果不同:

1)旧式课堂

 class Person(): _names_cache = {} def __init__(self,name): self.name = name def __new__(cls,name): return cls._names_cache.setdefault(name,object.__new__(cls,name)) ahmed1 = Person("Ahmed") ahmed2 = Person("Ahmed") print ahmed1 is ahmed2 print ahmed1 print ahmed2 >>> False <__main__.Person instance at 0xb74acf8c> <__main__.Person instance at 0xb74ac6cc> >>> 

2)新式课程

 class Person(object): _names_cache = {} def __init__(self,name): self.name = name def __new__(cls,name): return cls._names_cache.setdefault(name,object.__new__(cls,name)) ahmed1 = Person("Ahmed") ahmed2 = Person("Ahmed") print ahmed2 is ahmed1 print ahmed1 print ahmed2 >>> True <__main__.Person object at 0xb74ac66c> <__main__.Person object at 0xb74ac66c> >>> 

新的类inheritance自object ,必须在Python 2.2之后(即class Classname(object):而不是class Classname:编写。 核心的变化是统一types和类,这个好的副作用是它允许你从内置typesinheritance。

阅读descrintro了解更多详情。

新的风格类可能会使用super(Foo, self) ,其中Foo是一个类, self是实例。

super(type[, object-or-type])

返回一个将方法调用委托给父类或兄弟类的代理对象。 这对访问在类中被覆盖的inheritance方法很有用。 search顺序与getattr()使用的顺序相同,只是跳过了types本身。

而在Python 3.x中,您可以简单地在不带参数的类中使用super()

或者说,你应该总是使用新风格的类, 除非你的代码需要与2.2以前版本的Python一起工作。