By using this site, you agree to our updated Privacy Policy and our Terms of Use. Manage your Cookies Settings.
446,259 Members | 1,346 Online
Bytes IT Community
+ Ask a Question
Need help? Post your question and get tips & solutions from a community of 446,259 IT Pros & Developers. It's quick & easy.

Using super()

P: n/a
Hello,
I have a class called MyConfig, it is based on Python's
ConfigParser.ConfigParser.
It implements add_section(self, section), which is also implemented on
ConfigParser.ConfigParser, which I want to call.
So, reducing the problem to the bare minimum, the class (with a useless
add_section that shows the problem):
>>class MyConfig(ConfigParser):
.... def add_section(self, section):
.... super(MyConfig, self).add_section(section)
....

Create an object
>>m = MyConfig()
and call the problematic method:
>>m.add_section("blah")
Traceback (most recent call last):
File "<stdin>", line 1, in ?
File "<stdin>", line 3, in add_section
TypeError: super() argument 1 must be type, not classobj
>>>
Why is super() requiring a type ? doesn't it work with classes ? Is there a
way to achieve what I am trying to do (other than calling the specific
class that happens to be the parent today) ?

Thanks.
--
Pupeno <pu****@pupeno.com(http://pupeno.com)
Jul 19 '06 #1
Share this Question
Share on Google+
7 Replies


P: n/a
Pupeno írta:
Hello,
I have a class called MyConfig, it is based on Python's
ConfigParser.ConfigParser.
It implements add_section(self, section), which is also implemented on
ConfigParser.ConfigParser, which I want to call.
So, reducing the problem to the bare minimum, the class (with a useless
add_section that shows the problem):
The problem is that ConfigParser.ConfigParser is an old style class. It
is in the standard library, so I have no clue why. For old style
classes, you should directly call the ancestor class method.
For new style classes it works just fine:
class ConfigParser(object):
def add_section(self, section):
print section, "in ",self.__class__.__name__

class MyConfig(ConfigParser):
def add_section(self, section):
super(MyConfig, self).add_section(section)

m = MyConfig()
m.add_section("blah")
The output:

blah in MyConfig

Jul 19 '06 #2

P: n/a
Laszlo Nagy wrote:
Pupeno Ã*rta:
>Hello,
I have a class called MyConfig, it is based on Python's
ConfigParser.ConfigParser.
It implements add_section(self, section), which is also implemented on
ConfigParser.ConfigParser, which I want to call.
So, reducing the problem to the bare minimum, the class (with a useless
add_section that shows the problem):
The problem is that ConfigParser.ConfigParser is an old style class. It
is in the standard library, so I have no clue why. For old style
classes, you should directly call the ancestor class method.
For new style classes it works just fine:
class ConfigParser(object):
def add_section(self, section):
print section, "in ",self.__class__.__name__

class MyConfig(ConfigParser):
def add_section(self, section):
super(MyConfig, self).add_section(section)

m = MyConfig()
m.add_section("blah")
I see, thank you.

class MyConfig(ConfigParser, object):
def add_section(self, section)
super(MyConfig, self).add_section(section)

seems to work and as expected. Is there anything wrong with it ?
--
Pupeno <pu****@pupeno.com(http://pupeno.com)
Jul 19 '06 #3

P: n/a
I see, thank you.

class MyConfig(ConfigParser, object):
def add_section(self, section)
super(MyConfig, self).add_section(section)

seems to work and as expected. Is there anything wrong with it ?
I have never seen this before. :) I don't know the answer, but I'm
interested too.

Laszlo

Jul 19 '06 #4

P: n/a

Pupeno wrote:
I see, thank you.

class MyConfig(ConfigParser, object):
def add_section(self, section)
super(MyConfig, self).add_section(section)

seems to work and as expected. Is there anything wrong with it ?
Wow.

I highly recommend not doing this, unless the new type system was
designed to allow this sort of mixing, which I highly doubt. There are
some significant under-the-cover differences between old- and new-style
classes that could mess everything up when trying to mix them.
Carl Banks

Jul 19 '06 #5

P: n/a
Pupeno <pu****@pupeno.comwrote:
class MyConfig(ConfigParser, object):
def add_section(self, section)
super(MyConfig, self).add_section(section)

seems to work and as expected. Is there anything wrong with it ?
yes.

(1) There's a colon missing in the def-line. ;-)

(2) The folling doesn't work as you might expect:

----------------------------------------------8<---------------
from ConfigParser import ConfigParser
class MyConfig(ConfigParser, object):
def add_section(self, section):
print "in MyConfig"
super(MyConfig, self).add_section(section)

class AnotherConfig(object):
def add_section(self, section):
print "in AnotherConfig"
super(AnotherConfig, self).add_section(section)

class TheConfigIReallyUse(MyConfig, AnotherConfig):
def add_section(self, section):
print "in TheConfigConfigIReallyUse"
super(TheConfigIReallyUse, self).add_section(section)

a = TheConfigIReallyUse()

a.add_section(None)
---------------------------------------------->8---------------

If you call this little script, you get ...

----------------------------------------------8<---------------
in TheConfigConfigIReallyUse
in MyConfig
---------------------------------------------->8---------------

...., i. e. add_section in AnotherConfig won't be called.

The reason for this is, that the usage of "super" (or it's non-usage
in this case) is part of the interface of a class. ConfigParser doesn't
support super (as most if not all classes in the standard lib),
therefore it doesn't ensure AnotherConfig's add_section will be called
at an appropriate time. This call just gets lost.

In my world you should never user super with the only exception being
that you really know what you are doing. ;-) In fact, super is a cool
thing for non-trivial diamond shape inheritance (i.e. not counting
object to introduce the diamond shape, otherwise this would make every
multiple inheritance of new style classes a diamond shape). Even then
you have to be careful, that all methods must have the same signature
(*args and **kwargs may help you with this), because in the end you
never know which class calls which other class next. (Well, yes, you
may find out, but the next inheritance may break this again.)

In the end it comes down to:
(1) If you use diamond shape inheritance (or might in the
future), then use super.
(2) If your base classes support super, use super.
(3) If (1) goes without (2) be extra careful.
(4) Whatever you do, read the documentation of super and try to
understand what you are doing.
(5) If you want to know about the flamewar sourrounding this issue,
google for "python", "super" and "harmful"...

Cheers,
--Jan Niklas
Jul 19 '06 #6

P: n/a
Carl Banks ha scritto:
Pupeno wrote:
I see, thank you.

class MyConfig(ConfigParser, object):
def add_section(self, section)
super(MyConfig, self).add_section(section)

seems to work and as expected. Is there anything wrong with it ?

Wow.

I highly recommend not doing this, unless the new type system was
designed to allow this sort of mixing, which I highly doubt. There are
some significant under-the-cover differences between old- and new-style
classes that could mess everything up when trying to mix them.
I believe the new style system was designed to allows this sort of
mixing and
that there are no issues at all. A child of new style + old style is
simply a new
style class. If you do

class NewStyle(OldStyle, object):
pass

you will see that

type(NewStyle) == type

There should be something more on
http://www.python.org/download/relea...2.3/descrintro

(I have seen somewhere how type.__new__ works, and how the metaclass
is chosen, so I am pretty sure sure there are no issue, at least for
pure Python
classes).

Michele Simionato

Jul 20 '06 #7

P: n/a
Michele Simionato ha scritto:
I believe the new style system was designed to allows this sort of
mixing and
that there are no issues at all.
Thinking a bit more, there are no issues at all if you know what a new
style class is and if you do not expect it to work as an old-style one
;) For the benefit of the OP, it may be useful to notice that there are
a few differences, most notably on how special methods works. Here is
an example:

class Old:
pass

old = Old()

old.__str__ = lambda : 'hello!'

print old # special methods defined on the instance are recognized

class New(Old, object):
pass

new = New()

new.__str__ = lambda : 'hello!' # special methods defined on the
instance are not recognized

print new
HTH,

Michele Simionato

Jul 20 '06 #8

This discussion thread is closed

Replies have been disabled for this discussion.