What is the semantics meaning of 'object'?

Steven D'Aprano steve+comp.lang.python at pearwood.info
Sun Jun 23 14:46:07 EDT 2013


On Sun, 23 Jun 2013 12:49:42 -0400, Roy Smith wrote:

> One thing I've never understood about Python 2.x's multiple inheritance
> (mostly because I almost never use it) is how you do something like
> this:
> 
> class Base1(object):
>    def __init__(self, foo):
>       self.foo = foo
> 
> class Base2(object):
>    def __init__(self, bar):
>       self.bar = bar
> 
> class Derived(Base1, Base2):
>    def __init__(self, foo, bar):
>       # now what???
> 
> I need to call __init__() in both of my base classes.  I don't see how
> super() can do that for me.

It doesn't, and it can't, because your classes are not cooperative. The 
problem is, Derived.__init__ needs to call two super methods, but both of 
them require different arguments. If this was an ordinary method, you'd 
probably see the flaw straight away:

class Artist:
    def draw(self, painting): ...

class Gambler:
    def draw(self, cards): ...

class GamblingArtist(Gambler, Artist):
    def draw(self, painting, cards):
        ...


Here you've got two completely different actions that merely share the 
same name, is it really sensible to have *one* method try to do both? And 
if so, you certainly can't expect an automated call to work out which 
argument goes to which superclass. So here's a place where cooperative 
multiple inheritance  doesn't work, and you're reduced to either manually 
calling the methods (and hoping that they don't, in turn, end up in some 
sort of diamond inheritance diagram, which would be bad), or else you 
have to redesign your classes to be more cooperative.

This is one of the reasons why many languages simply prohibit multiple 
inheritance outright, except perhaps for mixins, or at least require that 
all methods have compatible signatures.

All is not lost, there are ways to make your classes cooperative. The 
trick is to have your classes' __init__ methods ignore keyword arguments 
they don't know what to do with. object used to do the same thing, but it 
no longer does, so you need to add an extra class just before object to 
swallow any args before they read object.


class Blocker(object):
    def __init__(self, **kwargs):
        # Block kwargs from reaching object
        super(Blocker, self).__init__()

class Base1(Blocker):
    def __init__(self, foo, **kwargs):
        self.foo = foo
        super(Base1, self).__init__(**kwargs)

class Base2(Blocker):
    def __init__(self, bar, **kwargs):
        self.bar = bar
        super(Base2, self).__init__(**kwargs)

class Derived(Base1, Base2):
    def __init__(self, foo, bar):
        super(Derived, self).__init__(foo=foo, bar=bar)


This may seem like a lot of work, but nobody said that cooperative 
multiple inheritance with different method signatures was easy!

The reality is, multiple inheritance is *hard*. Mixins and traits remove 
most of the problems, so if all you've ever used MI for is mixing in new 
behaviour, you won't get just how hard it really is. The best way to do 
MI is not to do it at all. But if you have to use it, then super is the 
only way to do it *right*. Anything else, and you're almost certainly 
either duplicating what super would do, or you've got bugs in your code.

Anyway, here are some links about super:

Super considered Super:
http://rhettinger.wordpress.com/2011/05/26/super-considered-super/

Here's a set of three posts, written quite a long time ago but still 
relevant, dissecting super in gory detail:

http://www.artima.com/weblogs/viewpost.jsp?thread=236275
http://www.artima.com/weblogs/viewpost.jsp?thread=236278
http://www.artima.com/weblogs/viewpost.jsp?thread=237121

and a more recent update:

http://www.artima.com/weblogs/viewpost.jsp?thread=281127

and a counter-argument, provocatively titled "Super considered Harmful", 
although the author backs away from this claim, since it turns out that 
the problems are not *super* but multiple inheritance itself.

https://fuhm.net/super-harmful/

Despite telling people not to use super, James Knight doesn't actually 
give them a better alternative. I believe this is because he can't -- 
super is the worst solution to multiple inheritance except for all the 
others.



-- 
Steven



More information about the Python-list mailing list