-1

I'm trying to figure out how to roughly do what is below. Some things will only have foo, some will have both foo and bar, and some will have foo, bar, and baz. I would like to be able to either call Child.calc(10) or GrandChild.calc(10) and get the attributes set correctly as needed.

At the end of building out multiple instances of Initial, Child, and Grandchild, I would like to just call calc on any of them and have it work, regardless of what class they are. Initially I was going to do calc_initial, calc_child, calc_grandchild, but that seemed wrong.

Initial Code

class Initial:
    def __init__(self, foo):
        self.foo = foo

    def Calc(self, amount):
        self.TotalFoo = self.foo * amount

class Child(Initial):
    def __init__(self, foo, bar):
        Initial.__init__(self, foo)
        self.bar = bar

    def Calc(self, amount):
        self.TotalBar = self.bar * amount

class GrandChild(Child):
    def __init__(self, foo, bar, baz):
        Child.__init__(self, foo, bar)
        self.baz = baz

    def Calc(self, amount):
        self.TotalBaz = self.baz * amount


GrandChild(10, 20, 30)
GrandChild.Calc(10)
print(GrandChild.TotalFoo)  # Want this to be 100
print(GrandChild.TotalBar)  # Want this to be 200
print(GrandChild.TotalBaz)  # Want this to be 300

Edited Code Thanks to mkrieger1

class Initial:
    def __init__(self, foo):
        self.foo = foo

    def calc(self, amount):
        self.total_foo = self.foo * amount

class Child(Initial):
    def __init__(self, foo, bar):
        Initial.__init__(self, foo)
        self.bar = bar

    def calc(self, amount):
        Initial.calc(self, amount)
        self.total_bar = self.bar * amount

class GrandChild(Child):
    def __init__(self, foo, bar, baz):
        Child.__init__(self, foo, bar)
        self.baz = baz

    def calc(self, amount):
        Child.calc(self, amount)
        self.total_baz = self.baz * amount

child = Child(2,4)
grandchild = GrandChild(10, 20, 30)
child.calc(10)
grandchild.calc(10)
print(child.total_foo)       # Want this to be 20 
print(child.total_bar)       # Want this to be 40
print(grandchild.total_foo)  # Want this to be 100
print(grandchild.total_bar)  # Want this to be 200
print(grandchild.total_baz)  # Want this to be 300

Trying to incorporate super but it feels like something is wrong. Results are correct but not sure.

class Initial:
    def __init__(self, foo):
        self.foo = foo

    def calc(self, amount):
        self.total_foo = self.foo * amount

class Child(Initial):
    def __init__(self, foo, bar):
        Initial.__init__(self, foo)
        self.bar = bar

    def calc(self, amount):
        super().calc(amount)
        self.total_bar = self.bar * amount

class GrandChild(Child):
    def __init__(self, foo, bar, baz):
        Child.__init__(self, foo, bar)
        self.baz = baz

    def calc(self, amount):
        super().calc(amount)
        self.total_baz = self.baz * amount

child = Child(2,4)
grandchild = GrandChild(10, 20, 30)
child.calc(10)
grandchild.calc(10)
print(child.total_foo)       # Want this to be 20 
print(child.total_bar)       # Want this to be 40
print(grandchild.total_foo)  # Want this to be 100
print(grandchild.total_bar)  # Want this to be 200
print(grandchild.total_baz)  # Want this to be 300

When trying to do elder's response

class Initial:
    def __init__(self, foo):
        self.foo = foo

    def calc(self, amount):
        self.total_foo = self.foo * amount

class Child(Initial):
    def __init__(self, foo, bar):
        super().__init__(foo)
        self.bar = bar

    def calc(self, amount):
        self.total_bar = self.bar * amount

class GrandChild(Child):
    def __init__(self, foo, bar, baz):
        super().__init__(foo, bar)
        self.baz = baz

    def calc(self, amount):
        self.total_baz = self.baz * amount

child = Child(2,4)
grandchild = GrandChild(10, 20, 30)
child.calc(10)
grandchild.calc(10)
print(child.total_foo)       # Want this to be 20 
print(child.total_bar)       # Want this to be 40
print(grandchild.total_foo)  # Want this to be 100
print(grandchild.total_bar)  # Want this to be 200
print(grandchild.total_baz)  # Want this to be 300

I get

     26 child.calc(10)
     27 grandchild.calc(10)
---> 28 print(child.total_foo)       # Want this to be 20
     29 print(child.total_bar)       # Want this to be 40
     30 print(grandchild.total_foo)  # Want this to be 100

AttributeError: 'Child' object has no attribute 'total_foo'
  • I've renamed the methods and attributes to follow a more idiomatic Python style. – mkrieger1 Dec 18 '21 at 12:29
  • Thank you, wrote it up fast but you are 100% correct, I need to work on that. – Paracelsus Dec 18 '21 at 12:30
  • Is your question why you get errors when trying to call the methods? – mkrieger1 Dec 18 '21 at 12:30
  • I am trying to one figure out why the error for missing a positional argument happens, and two, just figure out the proper way to do roughly what I am trying to accomplish. Not sure if I am going about it wrong, or if I am just making a slight mis-step. – Paracelsus Dec 18 '21 at 12:31
  • You need to call the methods with an instance of the class, not with the class itself. – mkrieger1 Dec 18 '21 at 12:33
  • Does this answer your question? [TypeError: Missing 1 required positional argument: 'self'](https://stackoverflow.com/questions/17534345/typeerror-missing-1-required-positional-argument-self) – mkrieger1 Dec 18 '21 at 12:36
  • Edited question to try what you said, that makes a bit more sense but still unsure of what is happening. – Paracelsus Dec 18 '21 at 12:45
  • `Initial.calc` is never called, so `total_foo` isn't calculated. – mkrieger1 Dec 18 '21 at 12:58
  • That works! Thank you so much. I edited the above question to include what I think is the working version of this. Are there any ways to improve? – Paracelsus Dec 18 '21 at 13:04
  • See https://stackoverflow.com/questions/805066/how-do-i-call-a-parent-classs-method-from-a-child-class-in-python – mkrieger1 Dec 18 '21 at 13:14
  • Edited initial question to include unedited code, and where I ended up. Still lost a bit trying to incoporate super. I feel like how I have it above, while it works, may be doing too much? – Paracelsus Dec 18 '21 at 13:53

1 Answers1

0
    class Initial:
    def __init__(self, foo):
        self.total_foo = None
        self.foo = foo

    def calc(self, amount):
        self.total_foo = self.foo * amount


class Child(Initial):
    def __init__(self, foo, bar):
        super().__init__(foo)
        self.total_bar = None
        self.bar = bar

    def calc(self, amount):
        self.total_bar = self.bar * amount
        return self.total_bar


class GrandChild(Child):
    def __init__(self, foo, bar, baz):
        super().__init__(foo, bar)
        self.total_baz = None
        self.baz = baz

    def calc(self, amount):
        self.total_baz = self.baz * amount
        return self.total_baz


child = Child(2, 4)
grandchild = GrandChild(10, 20, 30)
child.calc(10)
grandchild.calc(10)
print(child.total_foo)  # Want this to be 20
print(child.total_bar)  # Want this to be 40
print(grandchild.total_foo)  # Want this to be 100
print(grandchild.total_bar)  # Want this to be 200
print(grandchild.total_baz)

Use super().__init__(values) to pass the value to the parent class.

  • Having an issue getting this to work. Could you potentially make it more clear with calling calc on Child(2,4) and GrandChild(10,20,30) . AttributeError: 'Child' object has no attribute 'total_foo' – Paracelsus Dec 18 '21 at 13:40
  • I have updated the answer. You will not get your desire result because of the way you you are calculating values. You are overwriting calc method in Child and Grandchild class. –  Dec 18 '21 at 14:40