tags:

views:

101

answers:

3

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

+3  A: 

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.

steveha
Thanks for the interesting links. See my latest comments for why A is old-style.
haridsv
I apologize for not understanding what you were asking; I must have been tired last night when I wrote this. I have written a second answer that is better.
steveha
A: 

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.

Denis Otkidach
I would agree with you, however, class A is generated. For the context, the tool I am talking about is the ZSI package which gives wsdl2py and wsdl2dispatch tools. They have not been maintained since sometime in 2007, so not sure when they will update it for python 3.0. Right now, I am still using 2.6, so I don't have a problem with these generated classes. I haven't even seen an alternative newer package for implementing SOAP server.
haridsv
+1  A: 

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.

steveha