所有Python类都应该扩展对象吗?


129

我发现以下两项工作:

class Foo():
    def a(self):
        print "hello"

class Foo(object):
    def a(self):
        print "hello"

所有Python类都应该扩展对象吗?不扩展对象是否存在任何潜在问题?


2
有没有之间的差异class Foo():class Foo:?正如我所观察到的,它们都可以在Python 3中工作
Wolf

这个问题的答案很好:stackoverflow.com/questions/4015417/…–
nngeek

Answers:


117

在Python 2中,不继承自object将创建一个旧式类,除其他效果外,该类还会导致type产生不同的结果:

>>> class Foo: pass
... 
>>> type(Foo())
<type 'instance'>

>>> class Bar(object): pass
... 
>>> type(Bar())
<class '__main__.Bar'>

多重继承的规则也不同在这里我什至不尝试总结。我所见过的有关MI的所有好的文档都描述了新型类。

最终,旧式类在Python 3中消失了,并且继承自object隐式了。因此,除非您需要与旧软件向后兼容,否则请始终偏爱新样式类。


68

在Python 3中,object无论您是否自己说,类都隐式扩展。

在Python 2中,有旧式和新式类。要发出新的类信号,您必须显式继承自object。如果不是,则使用旧式实现。

通常,您需要一个新式的类。object显式继承。请注意,这也适用于旨在与Python 2兼容的Python 3代码。


是的,Free Foo指出的区别已经消失了,顺便说一句:空括号是可选的吗?

4
有很多使用foo(object):的python 3代码。那只是一个约定吗?
RFV5s

2
@RFVenter可能是应该同时在Python 2和3下运行的代码,在这种情况下,您需要显式地子类化对象,以使该类在Python 2下的行为基本相同
。– blubberdiblub

@blubberdiblub这就是我怀疑但我们的项目仅在python 3.5 virtualenv上运行的原因。我认为代码一定是从python 2项目复制的。
RFV5s

@RFVenter是的,这可能是另一种解释。当然,如果现在仅使用Python 3.x,则可以摆脱对象引用。
blubberdiblub

17

在python 3中,您可以通过三种不同的方式创建一个类,并且在内部它们都相等(请参见示例)。创建类无关紧要,Python 3中的所有类都继承自称为object的特殊类 。类对象 是python中的基础类,并提供许多功能,例如双下划线方法,描述符,super()方法,property()方法等。

范例1。

class MyClass:
 pass

示例2

class MyClass():
 pass

范例3。

class MyClass(object):
  pass


我不确定我是否会追踪您。是的,直到相关为止,才可能与大多数人无关。
菲利普·阿德勒

@PhilipAdler通常假定它object引用了Built -in object。如果必须考虑到可以替换任何CPython的内置标识符,我们几乎不能对数据模型进行断言。可以严肃地争论一下,str因为有人可以赋值,所以并不总是接受字符串作为参数builtins.str = None吗?
努诺·安德烈'18

我一直看到这种说法是“广泛假设的”,并且我接受这样一种假设,即当前的每个实现都做出了这样的假设(这不是语言的要求),根据我的经验,大多数python程序员都不是我的经验见过就假设这个,知道它,甚至考虑过它。无论采用哪种方法,即使它是正确的,也普遍认为它的主张不会使我的等同性不是严格正确的主张无效。
菲利普·阿德勒

1

是的,所有Python类都应扩展(或更确切地说是子类,这里是Python)对象。尽管通常不会发生严重的问题,但在某些情况下(如具有多个继承树),这将很重要。这也确保了与Python 3的更好兼容性。


1
恰好,在技术上如果你不这样做,你会得到一个经典的类,但也有这个没有真正的优势,它不被巨蟒-3反正支持
最大ķ。

我很好奇为什么它提高了与python3的兼容性。据我了解,即使您未指定python3,它也会自动使其扩展对象,对吗?
Paul Lo 2014年

2
@PaulLo对,但是,如果您显式继承自对象,则在Python 2和Python 3上都将获得相同的(新样式)行为。这与更改Python 3的工作方式无关,而与正向操作有关-compatibility Python的2
pydsigner

这个建议看起来不太优雅,但是如果您使用Python2和Python3,它似乎很有效。但是在实践中它有多重要?

@Wolf取决于您在做什么。如果您有复杂的继承树,那么这很重要。如果希望您的类成为描述符,则必须使用new-style。如果您需要更深入的信息,可以单击stackoverflow.com/questions/54867/…中的链接。
pydsigner

1

正如其他答案所涵盖的那样,从对象继承Python 3是隐式的。但是他们没有说明您应该做什么以及什么是惯例。

Python 3文档示例全部使用以下约定的样式,因此,我建议您在以后使用Python 3的任何代码中都遵循此样式。

class Foo:
    pass

资料来源:https : //docs.python.org/3/tutorial/classes.html#class-objects

引用示例:

类对象支持两种操作:属性引用和实例化。

属性引用使用Python中所有属性引用使用的标准语法:obj.name。有效属性名称是创建类对象时在类名称空间中的所有名称。因此,如果类定义如下所示:

class MyClass:
    """A simple example class"""
    i = 12345

    def f(self):
        return 'hello world'

另一句话:

一般来说,实例变量用于每个实例唯一的数据,类变量用于类的所有实例共享的属性和方法:

class Dog:

    kind = 'canine'         # class variable shared by all instances

    def __init__(self, name):
        self.name = name    # instance variable unique to each instance

0

在python3中没有区别,但是在python2中不扩展object给您带来了老式的类;您想在旧类上使用新类。


2
这个答案是合理的,但是其他答复者可以更快或更详细地到达那里。这个答案并没有给页面增加任何价值。
Mark Amery
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.