0

Hello I'd like to use a class method that requires multiple arguments as well as an attribute from the class' __init__().

However, because I have to make this call several times, I'd like to avoid providing multiple arguments to each call. Therefore, I thought to make a child class which supplies the arguments such as below. However, I don't want to override the parent method in the child class.

Here are the two classes with an example call:

class Parent:
    def __init__(self, parent_arg: dict) -> None:
        self.parent_arg = parent_arg

    def create_child(self, child_arg):
        return Child(child_arg, self.parent_arg)

    def method_a(self, method_arg: str, child_arg: str) -> dict:
        self.method_b(method_arg, child_arg)

    def method_b(self, method_arg: str, child_arg: str) -> str:
        print(f"{self.parent_arg}, {child_arg}, and {method_arg}")


class Child(Parent):
    def __init__(self, child_arg: str, parent_arg: dict) -> None:
        super().__init__(parent_arg)
        self.child_arg = child_arg

    def method_a(self, method_arg: str = None) -> dict:
        return super().method_a(method_arg, self.child_arg)

    def method_b(self, method_arg: str) -> str:
        return super().method_b(method_arg, self.child_arg)


if __name__ == "__main__":
    parent_instance = Parent(parent_arg="Parent Argument")
    child_instance = parent_instance.create_child(child_arg="Child Argument")
    child_instance.method_a(method_arg="Method Argument")

Again, I'd like to be able to call the same method names from Parent and Child instances. However, I'd like the computation to be done in the parent class methods. Thank you so so much for any and all help.

Here's one solution without inheritance, however, I'm curious if there's a more elegant solution.

class Child:
    def __init__(self, child_arg: str, parent_arg: dict) -> None:
        self.parent = Parent(parent_arg)
        self.child_arg = child_arg

    def method_a(self, method_arg: str = None) -> dict:
        return self.parent.method_a(method_arg, self.child_arg)

    def method_b(self, method_arg: str) -> str:
        return self.parent.method_b(method_arg, self.child_arg)
5
  • 3
    If you need to do this, there's a problem with your design. You shouldn't use the same method names if you don't want the child to override. Commented May 19, 2022 at 19:57
  • @Barmar How can I then initialize an instance with access to parent class methods, that sets a self.child_arg so that I don't have to provide this argument to subsequent calls? Commented May 19, 2022 at 19:59
  • 2
    Are you sure that inheritance is appropriate with these two classes? Inheritance is used for IS-A relationships, not HAS-A. Commented May 19, 2022 at 20:02
  • It's hard to tell what you're really trying to accomplish from these generic classes. Can you post a real use case? Commented May 19, 2022 at 20:06
  • Looking at the if __name__ == "__main__", I'd like to be able to call child_instance.method_a(method_arg="Method Argument") rather than child_instance.method_a(method_arg="Method Argument", child_arg="Child Argument") Commented May 19, 2022 at 20:07

2 Answers 2

2

I think the answer you're looking for is don't override method_b in the Child class.

You might be thinking that the execution "goes" to the parent when you call super(), and that's not right. You're "in" the same object the entire time (the self). If you simple omit method_b from your child definition, the value of child_instance.method_b will be the parent's definition.

Basically, only override these methods in the child if you have additional or different behavior you want to implement.


EDIT based on OP's comment

Take a look at this. It lets you assign attributes to objects as you create them, so you can re-use them without having to provide them on every method call. It implements Parent so that it is unaware of / not concerned with the Child. All the Child does is override the methods so it can make use of the additional child_arg param.

class Parent:
    def __init__(self, parent_arg: str) -> None:
        self.parent_arg = parent_arg

    def method_a(self, method_arg: str) -> None:
        self.method_b(method_arg)

    def method_b(self, method_arg: str) -> None:
        print(f"self.parent_arg: {self.parent_arg}")
        print(f"method_arg: {method_arg}")


class Child(Parent):
    def __init__(self, child_arg: str, parent_arg: str) -> None:
        super().__init__(parent_arg)
        self.child_arg = child_arg

    def method_a(self, method_arg: str) -> None:
        super().method_a(method_arg)

    def method_b(self, method_arg: str) -> None:
        print(f"self.parent_arg: {self.parent_arg}")
        print(f"self.child_arg: {self.child_arg}")
        print(f"method_arg: {method_arg}")


if __name__ == "__main__":

    parent_instance = Parent(parent_arg="Parent Argument")
    print("parent_instance calling a:")
    parent_instance.method_a("Method Argument")

    print("child_instance calling a:")
    child_instance = Child(
        child_arg="Child Argument",
        parent_arg="Parent Argument",
    )
    child_instance.method_a("Method Argument")
Sign up to request clarification or add additional context in comments.

1 Comment

My goal is to call the parent method, but provide an argument from a child-class attribute in order to avoid having to provide this argument in every call.
1

If you don't want to call the child's method, call the method from a specific class directly instead of going through self.methodname.

    def method_a(self, method_arg: str, child_arg: str) -> dict:
        return Parent.method_b(self, method_arg, child_arg)

1 Comment

I cannot use a static method, because the parent class method_b requires an attribute from the parent class' __init__().

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.