Home > Enterprise >  Why when using super().__init__ I can only initialize first parameter in parent class
Why when using super().__init__ I can only initialize first parameter in parent class

Time:07-01

Don't understand why this works:

class Fish:
    def __init__(self, first_name, last_name="Fish"):
        self.first_name = first_name
        self.last_name = last_name

class Trout(Fish):
    def __init__(self, water = "freshwater"):
        self.water = water
        super().__init__(self)

terry = Trout()

# Initialize first name
terry.first_name = "Terry"

# Use parent __init__() through super()
print(terry.first_name   " "   terry.last_name)

# Use child __init__() override
print(terry.water)

But if I would like every child class to have different last_name y can't delete its value and define it later like we did with first_name:

class Fish:
    def __init__(self, first_name, last_name):
        self.first_name = first_name
        self.last_name = last_name

class Trout(Fish):
    def __init__(self, water = "freshwater"):
        self.water = water
        super().__init__(self)

terry = Trout()

# Initialize first name
terry.first_name = "Terry"
terry.last_name =  "Crews"

# Use parent __init__() through super()
print(terry.first_name   " "   terry.last_name)

# Use child __init__() override
print(terry.water)

Error: TypeError: Fish.init() missing 1 required positional argument: 'last_name'

Thanks for the help.

CodePudding user response:

If you want to set the attributes in the constructor, you need to actually pass them as arguments; your child class needs to accept them as arguments so that it can pass them to the parent class.

class Fish:
    def __init__(self, first_name, last_name):
        self.first_name = first_name
        self.last_name = last_name

class Trout(Fish):
    def __init__(self, first_name, last_name, water = "freshwater"):
        self.water = water
        super().__init__(first_name, last_name)

terry = Trout("Terry", "Crews")

print(terry.first_name   " "   terry.last_name)
print(terry.water)

If you don't plan to use the constructor to set the attributes, remove those parameters and just set the attributes to default values (e.g. None):

class Fish:
    def __init__(self):
        self.first_name = None
        self.last_name = None

class Trout(Fish):
    def __init__(self, water = "freshwater"):
        self.water = water
        super().__init__()

terry = Trout()
terry.first_name = "Terry"
terry.last_name = "Crews"

print(terry.first_name   " "   terry.last_name)
print(terry.water)

You can also provide defaults in the parent class that are overridden by defaults in the child class that can in turn by overridden by optional arguments, e.g.:

class Fish:
    def __init__(self, water, first_name, last_name="Fish"):
        self.water = water
        self.first_name = first_name
        self.last_name = last_name

class Trout(Fish):
    def __init__(self, first_name, last_name="Trout"):
        super().__init__("freshwater", first_name, last_name)

terry = Trout("Terry", "Crews")

print(terry.first_name   " "   terry.last_name)
print(terry.water)

CodePudding user response:

You are not initialising any arguments of the parent class since child class doesn't have the necessary information. Also you don't need to provide self when calling super.

CodePudding user response:

When using super().__init__() method, you need to precise the parameters you are inheriting. and even inside your Trout constructor you need to mention all its parameters including the ones its inheriting i.e def __init__(self, first_name, last_name, water="freshwater"). So your Trout class should look like the code below

class Trout(Fish):
  def __init__(self, first_name, last_name, water="freshwater"):
    self.water=water
    super().__init__(first_name, last_name)
  • Related