为什么Python类继承对象?

为什么下面的类声明继承自object

class MyClass(object):...
414142 次浏览

是的,它是历史。没有它,它会创建一个旧式类。

如果你在旧式对象上使用type(),你只会得到“实例”。在新式对象上,你会得到它的类。

是的,这是一个“新样式”对象。这是python2.2中引入的一项功能。

新样式对象与经典对象有不同的对象模型,有些东西不能与旧样式对象正常工作,例如,super()@property和描述符。有关新样式类的良好描述,请参阅这篇文章

关于差异描述的链接:Python中的旧样式和新样式类有什么区别?

python3

  • class MyClass(object):=新样式类
  • class MyClass:=新样式类(隐式继承自object

python2

  • class MyClass(object):=新样式类
  • class MyClass:=老式班

补充说明

在Python 3. x中定义基类时,您可以从定义中删除object。然而,这可能会为一个非常难以跟踪的问题打开大门…

Python在Python 2.2中引入了新式类,到目前为止,旧式类真的很古老。对旧式类的讨论是埋在2. x文档中,在3. x文档中不存在。

问题是,Python 2. x中旧式类的语法与Python 3. x中新式类的替代语法相同。Python 2. x仍然被非常广泛地使用(例如GAE、Web2Py),任何代码(或编码器)无意中将3. x风格的类定义引入2. x代码中,最终都会得到一些严重过时的基本对象。而且因为老式类不在任何人的雷达上,他们可能不知道是什么打击了他们。

所以只要把它拼出来,省去一些2. x开发人员的眼泪。

历史艰难地学习Python

Python对一个类的原始呈现在许多严重的问题上被破坏了当这个错误被发现的时候已经太迟了,他们必须支持它。为了解决这个问题,他们需要一些“新类”风格,以便“旧类”继续工作但是你可以使用新的更正确的版本。

他们决定,他们将使用一个词“对象”,小写,是您从中继承以创建类的“类”。它令人困惑,但是一个类从名为“对象”的类继承来创建一个类,但是它实际上不是一个对象,它是一个类,但不要忘记继承从对象。

也只是为了让你知道新式类和旧式类的区别是什么,新式类总是继承自object类或继承自object的另一个类:

class NewStyle(object):pass

另一个例子是:

class AnotherExampleOfNewStyle(NewStyle):pass

一个老式的基类看起来像这样:

class OldStyle():pass

一个老式的子类看起来像这样:

class OldStyleSubclass(OldStyle):pass

你可以看到Old Style基类不会从任何其他类继承,但是,Old Style类当然可以相互继承。从对象继承保证了每个Python类中的某些功能都是可用的。Python 2.2中引入了新的样式类

类创建语句的语法:

class <ClassName>(superclass):#code follows

在没有任何其他您特别想要继承的超类的情况下,superclass应该始终是#1,这是Python中所有类的根。

从技术上讲,#0是Python中“新式”类的根。但是今天的新式类就像是唯一的类风格一样好。

但是,如果你在创建类时没有显式使用object这个词,那么正如其他人提到的,Python 3. x隐式继承自object超类。但我想显式总是比隐式好(地狱)

参考

类声明是否有理由从object继承?

在Python 3中,除了Python 2和3之间的兼容性之外,没有理由。在Python 2中,很多原因


Python 2. x故事:

在Python 2. x(从2.2开始)中,有两种类型的类,具体取决于是否存在object作为基类:

  1. “经典”风格类:它们没有object作为基类:

    >>> class ClassicSpam:      # no base class...     pass>>> ClassicSpam.__bases__()
  2. "new" style classes: they have, directly or indirectly (e.g inherit from a built-in type), object as a base class:

    >>> class NewSpam(object):           # directly inherit from object...    pass>>> NewSpam.__bases__(<type 'object'>,)>>> class IntSpam(int):              # indirectly inherit from object......    pass>>> IntSpam.__bases__(<type 'int'>,)>>> IntSpam.__bases__[0].__bases__   # ... because int inherits from object(<type 'object'>,)

Without a doubt, when writing a class you'll always want to go for new-style classes. The perks of doing so are numerous, to list some of them:

  • Support for descriptors. Specifically, the following constructs are made possible with descriptors:

    1. classmethod: A method that receives the class as an implicit argument instead of the instance.
    2. staticmethod: A method that does not receive the implicit argument self as a first argument.
    3. properties with property: Create functions for managing the getting, setting and deleting of an attribute.
    4. __slots__: Saves memory consumptions of a class and also results in faster attribute access. Of course, it does impose limitations.
  • The __new__ static method: lets you customize how new class instances are created.

  • Method resolution order (MRO): in what order the base classes of a class will be searched when trying to resolve which method to call.

  • Related to MRO, super calls. Also see, super() considered super.

If you don't inherit from object, forget these. A more exhaustive description of the previous bullet points along with other perks of "new" style classes can be found here.

One of the downsides of new-style classes is that the class itself is more memory demanding. Unless you're creating many class objects, though, I doubt this would be an issue and it's a negative sinking in a sea of positives.


Python 3.x story:

In Python 3, things are simplified. Only new-style classes exist (referred to plainly as classes) so, the only difference in adding object is requiring you to type in 8 more characters. This:

class ClassicSpam:pass

完全等同于(除了他们的名字:-):

class NewSpam(object):pass

并对此:

class Spam():pass

所有人都有object在他们的__bases__中。

>>> [object in cls.__bases__ for cls in {Spam, NewSpam, ClassicSpam}][True, True, True]

那么,你该怎么办?

在Python 2中:总是显式继承#0。获得津贴。

在Python 3中:继承自object,如果你正在编写的代码试图与Python无关,也就是说,它需要在Python 2和Python 3中都能工作。否则不会,这真的没有区别,因为Python会在幕后为你插入它。