是否可以扩展旧的和新的样式类?

时间:2009-10-29 06:38:11

标签: python

当我扩展一些工具生成的类时,我没有意识到它们是旧的样式类,直到我尝试使用super()。 super()不适用于旧样式类,所以我收到了这个错误:

TypeError: super() argument 1 must be type, not classobj

例如,试试这个片段:

>>> class A:
...     def greet(self):
...         print "A says hi"
...
>>> class B(A):
...     def greet(self):
...         print "B says hi"
...
>>> super(B, B()).greet()
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
TypeError: super() argument 1 must be type, not classobj

我很好奇如果我从对象扩展B以使其成为新的样式类会发生什么,并且它似乎使super()工作。

>>> class B(A, object):
...     def greet(self):
...         print "B says hi"
...
>>> super(B, B()).greet()
A says hi

这是一个合适的解决方法还是稍后会产生一些不良后果?

3 个答案:

答案 0 :(得分:4)

Python中推荐使用新式类,因为它们是在Python 2.2中引入的。在Python 3.x中,只有新式类可用。因此,我建议您将类切换为新式。

我不知道你可能有任何实际问题。在大多数情况下,新式类只会带来新功能,例如super()实际工作。如果您的代码以棘手的方式依赖于旧式类的语义,那么该代码当然会破坏。 (想到的唯一例子是着名的Alex Martelli着名的Borg pattern。)

Here是Python参考手册的链接,用于讨论新样式类与旧样式(“经典”)类。 here是经典文章的链接,Guido van Rossum解释了为什么会引入新式课程。

我在代码中只使用了新式的类,我鼓励你这样做。

答案 1 :(得分:1)

如果您无法更改生成器以生成新样式类,则可以对文件进行后处理以使其成为新样式:

import re
pat = re.compile("^(.*class\s+\w+)(:.*)$")
out_file = open("edited_file.py", "w")
for line in open("generated_file.py"):
    m = pat.match(line)
    if m:
        line = m.group(1) + "(object)" + m.group(2) + "\n"
    out_file.write(line)

out_file.close()

如果您由于某种原因不想这样做,那么请确保继续并继承原始类和object。据我所知,这应该工作得很好;你的新课将是一个新式的课程。

本书Python in a Nutshell(作者:Alex Martelli,由O'Reilly出版)说,如果你声明一个带有基类的类,并且至少有一个基类是新式的,那么它总是一个新的式班。它没有列出与此操作相关的任何特殊警告或危险。我觉得你很高兴。

答案 2 :(得分:0)

除非某些方法依赖于经典语义或经典基础使用元类(后代的元类将始终是新式类),否则我认为混合经典类和新风类没有问题。

另一方面,我认为没有理由再使用经典课程,因此首选class A:更改为class A(object):