Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Multiple Inheritance Quirk, or Bug in Python?

I am writing a class which should subclass, amongst other classes, code.InteractiveInterpreter. For some reason, one of the methods that that class normally has (compile) is not available on its subclasses when you use multiple inheritance.

Single inheritance works fine:

>>> from code import InteractiveInterpreter
>>> class Single(InteractiveInterpreter): pass
...
>>> hasattr(Single(), 'compile')
True

Multiple inheritance does not:

>>> class Double(object, InteractiveInterpreter): pass
...
>>> hasattr(Double(), 'compile')
False

Flipped the order around though, it works:

>>> class Flipped(InteractiveInterpreter, object): pass
...
>>> hasattr(Flipped(), 'compile')
True

Is there some subtle detail of multiple inheritance that I'm unaware of that is preventing compile from being inherited in some cases, or is there a bug in Python causing this (given the name of the method in question is also the name of a built-in function, I feel like this might be possible.)

I'm trying to reproduce the issue with a class other than InteractiveInterpreter but am unable to... this works fine:

>>> class Original():
...     def compile(self): pass
...
>>> class Secondary(object, Original): pass
...
>>> hasattr(Secondary(), 'compile')
True

I'm using Python 2.7.11, 32 bit, on Windows 10.

like image 837
ArtOfWarfare Avatar asked Mar 09 '26 09:03

ArtOfWarfare


2 Answers

Are you sure Flipped produced the given results?

I get the following with a similar setup,

>>> from code import InteractiveInterpreter
>>> class Flipped(InteractiveInterpreter, object): pass
... 
>>> hasattr(Flipped(), 'compile')
True

Based on the source of the module, compile is not a method of the class but an instance attribute created on object initialization. It would make sense that inheriting from object first would not provide the attribute because it's __init__ is defined and the subclass doesn't call InteractiveInterpreter.__init__ to assign the attribute.

like image 99
Jared Avatar answered Mar 11 '26 23:03

Jared


I don't exactly know where the problem lies, but one workaround is to explicitly call the constructor of InteractiveInterpreter, where the compile method is actually defined:

class Double(object, InteractiveInterpreter):
    def __init__(self, *args, **kwargs):
        InteractiveInterpreter.__init__(self, *args, **kwargs)

Note that a simply calling to super(Double, self).__init__(...) does not suffice (at least in my environment). However, this works for me

>>> hasattr(Flipped(), 'compile')
True

My environment: Python 2.7.11 (default, Jan 5 2016, 12:49:55) [GCC 4.2.1 Compatible Apple LLVM 7.0.2 (clang-700.1.81)] on darwin

like image 35
David Zwicker Avatar answered Mar 11 '26 23:03

David Zwicker



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!