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.
精彩评论