What is the difference between old style and new style classes in Python?
在Python中,旧样式类和新样式类有什么区别?我应该什么时候用一个还是另一个?
从docs.python.org http:/ / / / / 2的参考datamodel.html #新风格和经典类:
Up to Python 2.1, old-style classes were the only flavour available to the user.
The concept of (old-style) class is unrelated to the concept of type:
ifx is an instance of an old-style class, thenx.__class__
designates the class ofx , buttype(x) is always. This reflects the fact that all old-style instances, independently of
their class, are implemented with a single built-in type, called
instance.New-style classes were introduced in Python 2.2 to unify the concepts of class and type.
A new-style class is simply a user-defined type, no more, no less.If x is an instance of a new-style class, then
type(x) is typically
the same asx.__class__ (although this is not guaranteed – a
new-style class instance is permitted to override the value returned
forx.__class__ ).The major motivation for introducing new-style classes is to provide a unified object model with a full meta-model.
It also has a number of immediate benefits, like the ability to
subclass most built-in types, or the introduction of"descriptors",
which enable computed properties.For compatibility reasons, classes are still old-style by default.
New-style classes are created by specifying another new-style class
(i.e. a type) as a parent class, or the"top-level type" object if no
other parent is needed.The behaviour of new-style classes differs from that of old-style
classes in a number of important details in addition to what type
returns.Some of these changes are fundamental to the new object model, like
the way special methods are invoked. Others are"fixes" that could not
be implemented before for compatibility concerns, like the method
resolution order in case of multiple inheritance.Python 3 only has new-style classes.
No matter if you subclass from
object or not, classes are new-style
in Python 3.
明智的声明:
新型类继承和对象,或从另一个新样式类。
1 2 3 4 5 | class NewStyleClass(object): pass class AnotherNewStyleClass(NewStyleClass): pass |
老式的班别。
1 2 | class OldStyleClass(): pass |
重要的行为变化之间的旧的和新的风格类
- 超级添加
- 维修设备(下面解释)
- 添加数据块
- 新型类对象不能被提出,除非
Exception (衍生从下面的例子) __slots__ 增值
MRO(法第阶)的变化
它是在这里提到的其他的答案是A,但混凝土的例子之间的差异和经典的补体C3 MRO(维修中使用的新型类)。
问题是(这其中包括阶属性的成员方法和变量)是在搜索的多继承。
经典的A班做深度第一搜索从左到右。在第一站的比赛。他们没有在
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 | 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是更多复杂的英语句子中的to a synthesize单。这是在这里详细解释。一个是,一个是它的阶级属性库是唯一的一次寻找其衍生类的所有一次。他们有
1 2 3 4 5 6 7 8 9 10 11 | 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) |
新型类对象不能被提出,除非从
你可以在Python 2.5的普通班,这在Python 2.6中移除。2.7.3:在Python
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 | # 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 |
旧样式类的属性仍然是marginally更快查找。这不是重要的,但可能是有用的在性能敏感的Python代码:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 | In [3]: class A: ...: def __init__(self): ...: self.a = 'hi there' ...: In [4]: class B(object): ...: def __init__(self): ...: self.a = 'hi there' ...: In [6]: aobj = A() In [7]: bobj = B() In [8]: %timeit aobj.a 10000000 loops, best of 3: 78.7 ns per loop In [10]: %timeit bobj.a 10000000 loops, best of 3: 86.9 ns per loop |
Guido在安切洛蒂的书面内幕型类,是一个非常伟大的文章,对新的风格和老式的Python类。
Python有只读型3类,甚至如果你写"老式的阶级,它是从
新型类有一些先进的功能缺乏老式类,如《
这是一个非常实用,真/假差。唯一的两个版本之间的差异是在下面的代码(第二版inherits从对象的人。比其他,这两个版本是相同的,但不同的结果:
1)老派风格类
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 | 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)新型类
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 | 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> >>> |
一类新型的
descrintro读的更多细节。
新型类可能是一个在使用
super(type[, object-or-type]) Return a proxy object that delegates method calls to a parent or sibling class of type. This is useful for accessing inherited methods that have been overridden in a class. The search order is same as that used by getattr() except that the type itself is skipped.
你可以在Python 3.x和简单的使用
你应该总是使用或不是,新样式类,除非你有这样的代码需要与旧版本的Python 2.2)比。