为什么从对象继承会在Python中产生影响?

Why does inheriting from object make a difference in Python?

本问题已经有最佳答案,请猛点这里访问。

当类从任何东西继承时,我有一个实例类型的对象。

1
2
3
4
5
6
7
8
>>> class A(): pass;
>>> a = A()
>>> type(a)
<type 'instance'>
>>> type(a) is A
False
>>> type(A)
<type 'classobj'>

但是,当我从一个对象继承同一个类时,创建的对象是A类型。

1
2
3
4
5
6
7
8
>>> class A(object): pass;
>>> a = A()
>>> type(a)
<class '__main__.A'>
>>> type(a) is A
True
>>> type(A)
<type 'type'>

这背后的逻辑是什么?这是否意味着每个类都应该从对象继承?


在Python3中,这两者是相同的。但是,在Python2中:

1
2
3
class A: pass  # old-style class

class B(object): pass  # new-style class

从文档中的新样式和经典类:

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 classes and types. A new-style class is neither more nor less than a user-defined type. If x is an instance of a new-style class, then type(x) is the same as 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.

出于这些原因,随时使用新样式的类是个好主意。在python2.2+中存在旧样式类的唯一原因是为了向后兼容;在python3中,旧样式类被删除。


Python中用户定义类的原始实现很糟糕。2.2修复了它,但为了向后兼容,他们必须保留旧系统。因此,Python有两种类型的类:"经典"和"新样式"。从object继承的任何东西(直接或间接)都是新样式;任何不经典的东西都是经典的。您编写的每个类都应该以某种方式从对象继承,要么直接继承(如果它没有任何其他父类),要么间接继承(因为它继承了另一个新样式类(或内置类型)。

请参阅http://python-history.blogspot.com/2010/06/new-style-classes.html


这就解释了instance的事情:

1
2
3
4
5
>>> class A(): pass;
>>> A
<class __main__.A at 0x7f879998b050>
>>> A()                                            
<__main__.A instance at 0x7f87999a83b0>

但是您不应该使用type()来比较Python中的对象,您应该使用isinstance()