关于类:在Python中,旧样式类和新样式类有什么区别?

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:
if x is an instance of an old-style class, then x.__class__
designates the class of x, but type(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 as x.__class__ (although this is not guaranteed – a
new-style class instance is permitted to override the value returned
for x.__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班做深度第一搜索从左到右。在第一站的比赛。他们没有在__mro__属性。

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单。这是在这里详细解释。一个是,一个是它的阶级属性库是唯一的一次寻找其衍生类的所有一次。他们有__mro__属性这节目搜索命令。

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)

新型类对象不能被提出,除非从Exception衍生

你可以在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类,甚至如果你写"老式的阶级,它是从objectimplicitly衍生。

新型类有一些先进的功能缺乏老式类,如《super和C3 MRO,一些神奇的方法等。


这是一个非常实用,真/假差。唯一的两个版本之间的差异是在下面的代码(第二版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>
>>>


一类新型的object和AS搜索必须写在Python 2.2 onwards(IU class Classname(object):class Classname:代替)。核心是unify相变类型和类,和漂亮的附带效应,这是它允许你从一个内置的类型。

descrintro读的更多细节。


新型类可能是一个在使用super(Foo, self)Fooself是类和实例。

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和简单的使用super()inside a类在没有参数。


你应该总是使用或不是,新样式类,除非你有这样的代码需要与旧版本的Python 2.2)比。