Strange torch.nn.Module Behaviour with Multiple Inheritance ver. 2

Yuki-11: <p>I am trying to create a module class that inherits from two classes as follows:</p>
<pre><code class="lang-auto">from torch import nn

class Module1(nn.Module):
	def __init__(self):
		nn.Module.__init__(self)

		self.l1_loss = nn.L1Loss()


class Module2(nn.Module):
	def __init__(self, damy):
		nn.Module.__init__(self)
                self.damy = damy

class Module12(Module1, Module2):
	def __init__(self, damy):
		Module1.__init__(self)
		if hasattr(self, 'l1_loss'):
			print('l1_loss at position 1')

		Module2.__init__(self, damy)
		if hasattr(self, 'l1_loss'):
			print('l1_loss at position 2')
</code></pre>
<p>When I run the code, “l1_loss at position 1” is printed but not “l1_loss at position 2”. It seems that when Module2.<strong>init</strong>(self) is called, the member variable self.l1_loss is deleted. How can I create a module with multiple inheritance?</p>
<p>A problem very similar to this one is discussed in <a href="https://discuss.pytorch.org/t/strange-torch-nn-module-behaviour-with-multiple-inheritance/103629">this issue</a> and is solved by using the built-in function super (). However, in this code, the number of arguments given to the <strong>init</strong> method of Module1 and Module2 is different, so I think that super cannot be used.</p>

albanD: <p>Hi,</p>
<p>You should not call <code>Module1.__init__()</code> or even <code>nn.Module.__init__()</code> in your own function but <code>super().__init__()</code>.<br>
This will make sure that the multiple inheritance is properly handled.</p>

Yuki-11: <p>Thank you for your reply.</p>
<p>Following your advice, I tried to inherit the parent class of Module1 and Module2 with super () .__ init__ (), but now an error occurs. Here is the code and results.</p>
<pre><code class="lang-auto">from torch import nn

class Module1(nn.Module):
	def __init__(self):
		super().__init__()
		self.l1_loss = nn.L1Loss()


class Module2(nn.Module):
  def __init__(self, damy):
    super().__init__()
    self.damy = damy

class Module12(Module1, Module2):
  def __init__(self, damy):
    Module1.__init__(self)
    print(f"l1_loss at position 1:{hasattr(self, 'l1_loss')}")

    Module2.__init__(self, damy)
    print(f"l1_loss at position 2:{hasattr(self, 'l1_loss')}")
    print(f"damy at position 2:{hasattr(self, 'damy')}")

module12 = Module12("damy")


---------------------------------------------------------------------------
TypeError                                 Traceback (most recent call last)
&lt;ipython-input-24-e849cf8c32a4&gt; in &lt;module&gt;()
     21     print(f"damy at position 2:{hasattr(self, 'damy')}")
     22 
---&gt; 23 module12 = Module12("damy")

1 frames
&lt;ipython-input-24-e849cf8c32a4&gt; in __init__(self, damy)
     14 class Module12(Module1, Module2):
     15   def __init__(self, damy):
---&gt; 16     Module1.__init__(self)
     17     print(f"l1_loss at position 1:{hasattr(self, 'l1_loss')}")
     18 

&lt;ipython-input-24-e849cf8c32a4&gt; in __init__(self)
      3 class Module1(nn.Module):
      4         def __init__(self):
----&gt; 5                 super().__init__()
      6                 self.l1_loss = nn.L1Loss()
      7 

TypeError: __init__() missing 1 required positional argument: 'damy'

</code></pre>
<p>I guess it’s because the super () of Module1 that is called when Module12 does __init __ () of Module1 is reading the other parent class Module2 of the child class Module12.</p>
<p>In Module12, we can’t use super () because each parent class has a different number of arguments. If there is ways to solve this problem, please let me know.</p>

albanD: <p>A simple fix in your particular case is just to do <code>Module12(Module2, Module1)</code> to make the order go to Mod2 first and then Mod1:</p>
<pre><code class="lang-python">from torch import nn

class Module1(nn.Module):
    def __init__(self):
        print("Mod1 entry")
        super().__init__()
        print("Mod1 after super")
        self.l1_loss = nn.L1Loss()


class Module2(nn.Module):
  def __init__(self, damy):
    print("Mod2 entry")
    super().__init__()
    print("Mod2 after super")
    self.damy = damy

class Module12(Module2, Module1):
  def __init__(self, damy):
    print("Mod12 entry")
    super().__init__(damy)
    print("Mod12 after super")

print(Module12.__mro__)
module12 = Module12("damy")
</code></pre>

Yuki-11: <p>Thank you for your kind response! I didn’t know that the argument of super () flexibly supports multiple parent classes. I learned a lot.</p>