开发者

Is it OK to extend both old and new style classes?

When I extended some tool generated classes, I didn't realize that they are old style classes until I tried to use super(). The super() doesn't work with old style classes, so I got this error:

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

E.g., try this snippet:

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

I was just curious what开发者_StackOverflow社区 would happen if I extended B from object as well to make it a new style class, and it seemed to make super() work.

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

Is this an appropriate workaround or will I have some unwanted consequences later?


New-style classes have been recommended practice in Python since they were introduced in Python 2.2. In Python 3.x, only new-style classes are available. Therefore, I recommend you switch your classes to new-style.

I am not aware of any real problems you might have from this. For the most part, new-style classes simply bring new features, such as super() actually working. If you have code that relies on the semantics of old-style classes in tricky ways, that code would of course break. (The only example that comes to mind is the famous Borg pattern by the famous Alex Martelli.)

Here is a link to the Python reference manual for a discussion of new style classes vs. old-style ("classic") classes. And here is a link to the classic essay where Guido van Rossum explains why new-style classes were introduced.

I use only new-style classes in my code and I encourage you to do the same.


If you cannot change the generator to generate new-style classes, you could post-process the file to make them new-style:

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

If you don't want to do that for some reason, then sure, go ahead and subclass both the original class and object. To the best of my knowledge, that should work just fine; your new class will be a new-style class.

The book Python in a Nutshell (by Alex Martelli, published by O'Reilly) says that if you declare a class with base classes and at least one of the base classes is new-style, it will always be a new-style class. It does not list any special warnings or dangers related to this action. I think you are good to go.


I see no problem mixing classic and new-style classes unless some methods rely on classic semantic or your classic base uses metaclass (metaclass of offspring will be always a new-style class).

On the other hand I see no reason to use classic classes anymore, so changing class A: to class A(object): is preferred.

0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜