标签归档:object

Python类继承对象

问题:Python类继承对象

是否有理由要声明类object

我刚刚找到了执行此操作的代码,但找不到很好的理由。

class MyClass(object):
    # class code follows...

Is there any reason for a class declaration to inherit from object?

I just found some code that does this and I can’t find a good reason why.

class MyClass(object):
    # class code follows...

回答 0

是否有理由要声明类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. 具有property以下属性:创建用于管理属性的获取,设置和删除的功能。
    4. __slots__:节省了类的内存消耗,还可以更快地访问属性。当然,它确实有局限性
  • __new__静态方法:让您自定义如何将新创建类的实例。

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

  • 与MRO有关,请super调用。另见,super()算超级。

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

新型类的缺点之一是,类本身对内存的要求更高。但是,除非您要创建许多类对象,否则我怀疑这将是一个问题,并且它是一个消极的消极情绪。


Python 3.x故事:

在Python 3中,一切都得到了简化。仅存在新样式的类(统称为类),因此添加的唯一区别object是要求您再输入8个字符。这个:

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中: 始终object显式继承。享受津贴。

在Python 3中:object如果您要编写尝试与Python无关的代码,则继承自它,也就是说,它需要在Python 2和Python 3中均能正常工作。否则,实际上并没有什么不同,因为Python会为您插入代码在幕后。

Is there any reason for a class declaration to inherit from object?

In Python 3, apart from compatibility between Python 2 and 3, no reason. In Python 2, many reasons.


Python 2.x story:

In Python 2.x (from 2.2 onwards) there’s two styles of classes depending on the presence or absence of object as a base-class:

  1. “classic” style classes: they don’t have object as a base class:

    >>> 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

is completely equivalent (apart from their name :-) to this:

class NewSpam(object):
     pass

and to this:

class Spam():
    pass

All have object in their __bases__.

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

So, what should you do?

In Python 2: always inherit from object explicitly. Get the perks.

In Python 3: inherit from object if you are writing code that tries to be Python agnostic, that is, it needs to work both in Python 2 and in Python 3. Otherwise don’t, it really makes no difference since Python inserts it for you behind the scenes.


回答 1

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

Python 3

  • class MyClass(object): = New-style class
  • class MyClass: = New-style class (implicitly inherits from object)

Python 2

  • class MyClass(object): = New-style class
  • class MyClass: = OLD-STYLE CLASS

Explanation:

When defining base classes in Python 3.x, you’re allowed to drop the object from the definition. However, this can open the door for a seriously hard to track problem…

Python introduced new-style classes back in Python 2.2, and by now old-style classes are really quite old. Discussion of old-style classes is buried in the 2.x docs, and non-existent in the 3.x docs.

The problem is, the syntax for old-style classes in Python 2.x is the same as the alternative syntax for new-style classes in Python 3.x. Python 2.x is still very widely used (e.g. GAE, Web2Py), and any code (or coder) unwittingly bringing 3.x-style class definitions into 2.x code is going to end up with some seriously outdated base objects. And because old-style classes aren’t on anyone’s radar, they likely won’t know what hit them.

So just spell it out the long way and save some 2.x developer the tears.


回答 2

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

新样式对象与经典对象具有不同的对象模型,并且某些内容无法与旧样式对象一起正常工作,例如和super()@property以及描述符。有关什么是新样式类的详细说明,请参见本文

SO链接描述了这些差异:Python中旧样式类和新样式类之间有什么区别?

Yes, this is a ‘new style’ object. It was a feature introduced in python2.2.

New style objects have a different object model to classic objects, and some things won’t work properly with old style objects, for instance, super(), @property and descriptors. See this article for a good description of what a new style class is.

SO link for a description of the differences: What is the difference between old style and new style classes in Python?


回答 3

难学Python的历史:

Python最初对类的再现在很多方面都被破坏了。到发现此故障时,已经为时已晚,他们必须予以支持。为了解决该问题,他们需要某种“新类”样式,以便“旧类”继续工作,但是您可以使用更正确的新版本。

他们决定使用小写的“对象”一词作为继承自您的“类”以构成一个类。这很令人困惑,但是一个类继承自名为“ object”的类来构成一个类,但它实际上并不是一个对象,而是一个类,但不要忘记从object继承。

也只是为了让您知道新样式类和旧样式类之间的区别是,新样式类始终从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中引入了新样式类

History from Learn Python the Hard Way:

Python’s original rendition of a class was broken in many serious ways. By the time this fault was recognized it was already too late, and they had to support it. In order to fix the problem, they needed some “new class” style so that the “old classes” would keep working but you can use the new more correct version.

They decided that they would use a word “object”, lowercased, to be the “class” that you inherit from to make a class. It is confusing, but a class inherits from the class named “object” to make a class but it’s not an object really its a class, but don’t forget to inherit from object.

Also just to let you know what the difference between new-style classes and old-style classes is, it’s that new-style classes always inherit from object class or from another class that inherited from object:

class NewStyle(object):
    pass

Another example is:

class AnotherExampleOfNewStyle(NewStyle):
    pass

While an old-style base class looks like this:

class OldStyle():
    pass

And an old-style child class looks like this:

class OldStyleSubclass(OldStyle):
    pass

You can see that an Old Style base class doesn’t inherit from any other class, however, Old Style classes can, of course, inherit from one another. Inheriting from object guarantees that certain functionality is available in every Python class. New style classes were introduced in Python 2.2


回答 4

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

如果type()在旧式对象上使用,则只会得到“实例”。在新型对象上,您可以得到其类。

Yes, it’s historical. Without it, it creates an old-style class.

If you use type() on an old-style object, you just get “instance”. On a new-style object you get its class.


回答 5

类创建语句的语法:

class <ClassName>(superclass):
    #code follows

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

object从技术上讲,它是Python中“新型”类的根。但是,如今的新型类与唯一的类一样好。

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

参考

The syntax of the class creation statement:

class <ClassName>(superclass):
    #code follows

In the absence of any other superclasses that you specifically want to inherit from, the superclass should always be object, which is the root of all classes in Python.

object is technically the root of “new-style” classes in Python. But the new-style classes today are as good as being the only style of classes.

But, if you don’t explicitly use the word object when creating classes, then as others mentioned, Python 3.x implicitly inherits from the object superclass. But I guess explicit is always better than implicit (hell)

Reference