为什么 Python 类会继承对象?

Why do Python classes inherit object?

提问人:tjvr 提问时间:10/25/2010 最后编辑:Mateen Ulhaqtjvr 更新时间:4/9/2022 访问量:438171

问:

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

class MyClass(object):
    ...
Python OOP 对象 继承

评论

206赞 vastlysuperiorman 12/23/2015
这个问题的答案(虽然简单)很难找到。在谷歌上搜索诸如“python对象基类”之类的东西,会出现一页又一页的面向对象编程教程。点赞,因为这是引导我搜索词“旧式与新式 python 对象”的第一个链接
5赞 SLaks 10/25/2010
这将创建一个新样式的类
0赞 user202729 1/31/2021
对于“如何搜索这个问题”部分,SymbolHound 是一个选项。

答:

34赞 knitti 10/25/2010 #1

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

如果你在一个旧式的对象上使用,你只会得到“instance”。在新样式对象上,您可以获取其类。type()

评论

1赞 Joel Sjögren 2/15/2014
此外,如果你在旧式类上使用,你会得到“classobj”而不是“type”。type()
409赞 Jerub 10/25/2010 #2

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

新样式对象具有与经典对象不同的对象模型,并且某些功能无法正常用于旧样式对象,例如 和 描述符。请参阅本文,了解什么是新样式类。super()@property

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

评论

113赞 10/25/2010
+1 这个。请注意,旧式类在 Python 3 中已经消失了,因此您只需要在 Python 2 中继承。object
10赞 alwbtc 1/1/2016
这不是一个真正的答案。ı 只是参考了其他文章。我认为亚林的回答应该被接受为这个问题的答案。
2赞 ViFI 6/29/2016
@alwbtc:这个答案也有新的东西。例如,提到“super()”将我引向了另一个重要的[这里](stackoverflow.com/questions/576169/...
601赞 Yarin 2/26/2012 #3

Python 3 (英语)

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

Python 2 中文文档

  • 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 开发人员的眼泪。

评论

24赞 Aidis 12/12/2014
“在 Python 3.x 中定义基类时,您可以从定义中删除对象。然而,这可能会为一个非常难以追踪的问题打开大门......”你指的是什么问题?
9赞 ShadowRanger 12/9/2016
@Aidis:我认为他们的意思是,在 Py2 和 Py3 上运行的代码在 Py3 上是可以的,但是如果它依赖于新样式的类功能,则在 Py2 上会被破坏。就个人而言,如果我编写这样的代码,我会省略显式继承,而只是放在模块的顶部(在行之后:-));这是 Py2 中的兼容性黑客,默认情况下使模块中所有随后定义的类都是新样式的,而在 Py3 中,它被完全忽略(只是一个随机的全局变量),所以它是无害的。__metaclass__ = typefrom __future__ import absolute_import, division, print_function
37赞 disp_name 11/4/2014 #4

学习 Python 的艰难方式的历史:

Python 对类的原始演绎在许多严重的情况下被打破了 方式。当这个错误被识别出来时,已经太晚了, 他们必须支持它。为了解决这个问题,他们需要 一些“新类”风格,以便“旧类”继续工作 但你可以使用新的更正确的版本。

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

另外,只是为了让您知道新式类和旧式类之间的区别是什么,那就是新式类总是继承自 class 或从继承自 :objectobject

class NewStyle(object):
    pass

另一个例子是:

class AnotherExampleOfNewStyle(NewStyle):
    pass

虽然旧式基类如下所示:

class OldStyle():
    pass

一个老式的子类是这样的:

class OldStyleSubclass(OldStyle):
    pass

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

评论

10赞 abarnert 5/4/2015
调用根类并不是那么令人困惑,事实上它是非常标准的。Smalltalk 有一个名为 的根类,以及一个名为 的根元类。为什么?因为,就像狗的类一样,它是对象的类,也是类的类。Java、C#、ObjC、Ruby 和当今人们使用的大多数其他具有根类的基于类的 OO 语言都使用一些变体作为名称,而不仅仅是 Python。objectObjectClassDogObjectClassObject
9赞 kmario23 10/20/2016 #5

class creation 语句的语法:

class <ClassName>(superclass):
    #code follows

如果没有您特别想要继承的任何其他超类,则 应该始终是 object,它是 Python 中所有类的根。superclass

技术上讲,object 是 Python 中“新式”类的根。但今天的新式班级与唯一的班级一样好。

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

参考

1219赞 Dimitris Fasarakis Hilliard 7/12/2017 #6

类声明有什么理由继承吗?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. “新”样式类:它们直接或间接(例如从内置类型继承)作为基类:object

    >>> 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'>,)
    

毫无疑问,在编写课程时,您总是希望选择新风格的课程。这样做的好处很多,列举其中的一些:

  • 支持描述符。具体来说,以下构造可以通过描述符实现:

    1. classmethod:将类作为隐式参数而不是实例接收的方法。
    2. staticmethod:不接收隐式参数作为第一个参数的方法。self
    3. 属性与属性:创建用于管理属性的获取、设置和删除的函数。
    4. __slots__:节省类的内存消耗,并加快属性访问速度。当然,它确实施加了限制
  • __new__静态方法:允许您自定义创建新类实例的方式。

  • 方法解析顺序 (MRO):在尝试解析要调用的方法时,将以什么顺序搜索类的基类。

  • 与MRO有关,超级电话。另请参阅,super() 被认为是 super。

如果你不继承 ,忘记这些。可以在此处找到对前面要点的更详尽的描述以及“新”样式类的其他好处。object

新式类的缺点之一是类本身对内存的要求更高。但是,除非您正在创建许多类对象,否则我怀疑这会是一个问题,并且它是在积极因素的海洋中沉没的消极因素。


Python 3.x 故事:

在 Python 3 中,事情被简化了。只有新样式的类存在(简称为类),因此,添加的唯一区别是需要您再输入 8 个字符。这:object

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 中:始终显式继承对象。获得福利。

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

评论

1赞 bruno desthuilliers 3/19/2018
"depending on the presence or absence of a built-in type as a base-class" => actually it's not about "absence or presence of a builtin type as a base class" but wether the class inherits - directly or indirectly - from . IIRC there was a point in time where not all builtin types where ported to new-style classes yet.object
0赞 Dimitris Fasarakis Hilliard 3/20/2018
@brunodesthuilliers My impression was that all built-in types did inherit from . I do have a Python 2.2.3 around and after a quick check I couldn't find an offender but, I'll reword the answer later to make it more clear. Would be interested if you could find an example though, my curiosity is piqued.object
0赞 bruno desthuilliers 3/20/2018
In all honesty (cf the "IIRC" in my previous comment) I am not 101% sure about this point (wether all builtin types were already converted to new-style classes when new-style classes were introduced) - I might just be plain wrong, or this might only have concerned some of the standard lib's (but not builtin) types. But yet I think it should be better to clarify that what makes a new-style class is having in it's bases.object
1赞 ShadowRanger 4/2/2019
staticmethod and work just fine even on old-style classes. sorta works for reading on old-style classes, it just fails to intercept writes (so if you assign to the name, the instance gains an attribute of the given name that shadows the property). Also note that 's improvement to attribute access speed is mostly about undoing the loss that new-style class attribute access incurs, so it's not really a selling point of new-style classes (the memory savings are a selling point though).classmethodproperty__slots__
0赞 chepner 12/6/2022
Built-in classes (like , , etc) were converted to new-style classes early on, if not immediately. Class defined in pure Python in the standard library, though, were another matter. (Just to pick a random example, some private helper classes in the module did not explicitly inherit from , even in Python 2.7.)strinttarfileobject