当我扩展一些工具生成的类时,我没有意识到它们是旧的样式类,直到我尝试使用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
这是一个合适的解决方法还是稍后会产生一些不良后果?
答案 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):
。