oddness in super()

John Machin sjmachin at lexicon.net
Sun Jun 19 01:45:51 CEST 2005


Michael P. Soulier wrote:
> Ok, this works in Python on Windows, but here on Linux, with Python 2.4.1, I'm
> getting an error. 
> 
> The docs say:
> 
> A typical use for calling a cooperative superclass method is:
> 
> class C(B):
>     def meth(self, arg):
>         super(C, self).meth(arg)
> 
> However, when I try this, which works on windows, with ActiveState
> ActivePython 2.4.0...
> 
> class RemGuiFrame(RemGlade.RemFrame):
>     """This class is the top-level frame for the application."""
> 
>     def __init__(self, *args, **kwds):
>         "Class constructor."
>         # Constructor chaining
>         super(RemGuiFrame, self).__init__(*args, **kwds)
> 
> ...on linux I get this...
> 
> [msoulier at piglet pysrc]$ ./RemGui.py 
> Traceback (most recent call last):
>   File "./RemGui.py", line 206, in ?
>     frame_1 = RemGuiFrame(None, -1, "")
>   File "./RemGui.py", line 30, in __init__
>     super(RemGuiFrame, self).__init__(*args, **kwds)
> TypeError: super() argument 1 must be type, not classobj
> 
> Why the difference?

You are in the best position to answer that; you have access to the 
source code of the place where the problem occurs (RemGui.py), in both a 
"working" instance and a non-"working" instance, so you can (a) read it 
(b) debug it with a debugger, or insert print statements e.g. print 
repr(RemGuiFrame), repr(RemGlade.RemFrame)

You have already noted two variables, OS Windows/Linux, and Python 
2.4.[01]). Are there any others? Perhaps RemGlade.RemFrame comes from a 
3rd party library and there's a version difference.

> Is Python portability overrated?

No. Please stop baying at the moon, and dig out some evidence.

> Is this a bug? 

Is *what* a bug?

Is "it" a bug in what? Windows? Linux? Python 2.4.0? Python 2.4.1? 3rd 
party code? your code?

=====

I've never used "super" before, I'm only vaguely aware what it could be 
useful for, and what a "cooperative superclass method" might be, and I 
don't have access to your source code, nor to Linux ... but let's just 
see what can be accomplished if you drag yourself away from that moonlit 
rock and start digging:

First (1) Ooooh what a helpful error message! What is a "classobj"?

Let's RTFM: Hmmm don't tell X** L** but there's no entry for "classobj" 
in the index. But wait, maybe that's geekspeak for "class object" ...
two or three bounces of the pogo-stick later we find this:

"""
Class Types
Class types, or ``new-style classes,'' are callable. These objects 
normally act as factories for new instances of themselves, but 
variations are possible for class types that override __new__(). The 
arguments of the call are passed to __new__() and, in the typical case, 
to __init__() to initialize the new instance.

Classic Classes
Class objects are described below. When a class object is called, a new 
class instance (also described below) is created and returned. This 
implies a call to the class's __init__() method if it has one. Any 
arguments are passed on to the __init__() method. If there is no 
__init__() method, the class must be called without arguments.
"""

(2) Well fancy that... "type" kinda sorta means "new", "classobj" kinda 
sorta means "old"! Now let's re-read the bit about super in TFM:

"""
super() only works for new-style classes
"""

(3) So let's check out our tentative hypothesis:
"""
class Bold:
     def __init__(self):
         print "Bold"

class Bnew(object):
     def __init__(self):
         print "Bnew"

class Cold(Bold):
     def __init__(self):
         print "Cold", repr(Cold), "derives from", repr(Bold)
         super(Cold, self).__init__()
         print "Cold OK"

class Cnew(Bnew):
     def __init__(self):
         print "Cnew", repr(Cnew), "derives from", repr(Bnew)
         super(Cnew, self).__init__()
         print "Cnew OK"

cnew = Cnew()
cold = Cold()
"""

which when run on Python 2.4.1 on a Windows box produces this result:
"""
Cnew <class '__main__.Cnew'> derives from <class '__main__.Bnew'>
Bnew
Cnew OK
Cold <class __main__.Cold at 0x00ADF750> derives from <class 
__main__.Bold at 0x00ADF630>
Traceback (most recent call last):
   File "C:\junk\soulier.py", line 22, in ?
     cold = Cold()
   File "C:\junk\soulier.py", line 12, in __init__
     super(Cold, self).__init__()
TypeError: super() argument 1 must be type, not classobj

"""

Funny that, the class repr()s are different; not in a meaningful way, 
but the mere difference indicates the classes are products of different 
manufacturers.

(4) Ooooh! How old is the Linux copy of that 3rd party library?

(5) Looks like the bug is in RemGui.py -- it is calling super() with an 
invalid argument. No apparent Python portability problems.

> 
> I'm confused. 

Confession is good for the soul. However true confession is even better 
for the soul. Please come up with a better description. :-)

===

I hope these self-help hints are useful with your next "confusion".

Cheers,
John



More information about the Python-list mailing list