0

I'm having a problem with multiple inheritance that I can't seem to figure out. Here is a very abstracted minimal example that reproduces my error (my code is much more complex than this).

class Thing(object):
    def __init__(self, x=None):
        self.x = x

class Mixin(object):
    def __init__(self):
        self.numbers = [1,2,3]

    def children(self):
        return [super().__init__(x=num) for num in self.numbers]

class CompositeThing(Mixin, Thing):
    def __init__(self):
        super().__init__()

    def test(self):
        for child in self.children():
            print(child.x)

obj = CompositeThing()
obj.test()

Per this, I expect the children() method to return a list of Things built up from self.numbers. Instead, I get TypeError: super(type, obj): obj must be an instance or subtype of type. Incidentally, the same thing happens if I don't call the constructor and allow children to return super() 3 times (i.e., the uninstantiated superclass). Any ideas why this might be happening?

Thanks in advance!

Zen
  • 137
  • 5

2 Answers2

0

In line 9 of your code, it looks like you are trying to call __init__ of object. I am assuming you meant to have Mixin inherit from Thing.

class Thing(object):
    def __init__(self, x=None):
        self.x = x

class Mixin(Thing):
    def __init__(self):
        self.numbers = [1,2,3]

    def children(self):
        return [super().__init__(x=num) for num in self.numbers] # Now calls Thing.__init__ instead of object.__init__

class CompositeThing(Mixin, Thing):
    def __init__(self):
        super().__init__()

    def test(self):
        for child in self.children():
            print(child.x)

obj = CompositeThing()
obj.test()
Robinson
  • 300
  • 3
  • 12
  • This is incorrect. In reality there are many different kinds of `Thing`s, so Mixin needs to stand alone and yet be able to instantiate whatever `Thing` is. My understanding of the MRO is that this is possible - or is my understanding incorrect? – Zen Apr 12 '20 at 09:24
  • It is possible, but not using `super()`. Given that `Mixin` inherits directly from `object`, running `super()` will return `object` and not `Thing`. You can directly access `Thing` by using `Thing.__init__` instead of `super().__init__`. Perhaps a better solution would be to create another object which `Mixin` inherits from. – Robinson Apr 12 '20 at 09:35
  • the problem is I won't know what kind of `Thing` my `Mixin` class will need until the final child (i.e. the leaf of the inheritance tree) – Zen Apr 12 '20 at 18:09
  • also, that doesn't explain why just putting `super()` in the definition of `children()` fails with `TypeError: super(type, obj): obj must be an instance or subtype of type`, as opposed to simply returning 3 references to the `object` classes – Zen Apr 13 '20 at 05:38
0

Actually, I figured it out. There were two problems: (1) super() doesn't work as expected inside comprehensions because comprehensions in Py3 have their own scope - this was causing the TypeError I was experiencing. (2) What I was really trying to do was create a new instance of the parent, rather than calling a method from the parent. I have posted a new question for just the latter problem for clarity.

Zen
  • 137
  • 5