4

I need to merge two methods from different instances of different classes to a single instance of a class.

For example I define two classes:

class A:
    def __init__(self):
        self.name = "a"

    def print_name(self):
        print(self.name)


class B:
    def __init__(self):
        self.name = "b"

    def print_name(self):
        print(self.name)

and then I will try to make another object c and its print_name method must return the results of a.print_name() and b.print_name() so I tried the following :

a = A()
b = B()
c = A()

c.name = "c"
c.print_name_1 = a.print_name
c.print_name_2 = b.print_name
def final_print(self):
    self.print_name_1()
    self.print_name_2()
c.print_name = MethodType(final_print, c)
c.print_name()

Expected output:

c
c

but I get :

a
b

I tried to use types.MethodType as described here but it creates some kind of a method which takes two arguments : the first one will be the 'a' instance and the second one will be the 'c' instance.

Any help to do that properly?

Breeky
  • 61
  • 7
  • 2
    Overriding methods on a per-instance basis defeats the purpose of having a class, which is to provide a *uniform* interface for all instances of the class. – chepner Sep 04 '20 at 18:24
  • My goal is to create a new object by merging two others, I don't know how to do that with another way – Breeky Sep 04 '20 at 18:26
  • 2
    Should `c` be an instance of `A`, or should it really be an instance of a *new* class? Also, do `A` and `B` really need to be separate classes, or can `a` and `b` be instances of the same class, just with different values for the `name` attribute? – chepner Sep 04 '20 at 18:29
  • So a,b,c inherit from the same class, let's call it `Parent`, but they are different classes with different methods – Breeky Sep 04 '20 at 20:39

1 Answers1

1

I managed to succeed with this, thanks to this answer. I am using the __func__ attribute of a method. So here is the code :

c.name = "c"
c.print_name_1 = MethodType(lambda instance: copy.deepcopy(a.print_name).__func__(instance), c)
c.print_name_2 = MethodType(lambda instance: copy.deepcopy(b.print_name).__func__(instance), c)
def final_print(self):
    self.print_name_1()
    self.print_name_2()
c.print_name = MethodType(final_print, c)
c.print_name()
Breeky
  • 61
  • 7
  • 1
    While this works, it's probably not the correct solution to whatever end goal you are hoping to achieve. – tripleee Sep 06 '20 at 17:42
  • To describe more precisely my intend, it is to create a parent class Parent, and two types of parent called A and B which have their own implementation of the function print_name. Here I want to merge A and B to create a new class or instance dynamically (in the code above it is c) that has a function with the same name (i.e. print_name), and this function must execute first the method print_name defined in A, and then the method print_name defined in B. But the self argument in these functions refers to the instance c. So do you have any idea how to merge this methods into one dynamically ? – Breeky Sep 07 '20 at 18:10
  • That's still crazy. Why do you want to do that? Having methods with different names in A and B would let you easily have a wrapper which dispatches the method with a different name, so in A you would have `def method(): return(a_method)` and in B `def method: return(b_method)`. Now in C you can easily inherit from both A and B and `def method: a_method(); return b_method()` or whatever. – tripleee Sep 07 '20 at 18:14
  • 1
    Tangentially, maybe see also mixins. – tripleee Sep 07 '20 at 18:14
  • I need the methods to have the same name because my program works with sort of callbacks. At some point in the program I call instance_of_parent.print_name(). So that’s why I need to have a method print_name in c – Breeky Sep 08 '20 at 06:17
  • 1
    Yes yes, so define it like A: `def print_name(): return a_specific_print_name()` and B: `def print_name(): return b_specific_print_name()` and then in C `def print_name(): a_specific_print_name(); b_specific_print_name()` – tripleee Sep 08 '20 at 06:18