RVA92
RVA92

Reputation: 736

Dynamically adopt the methods of an instance of another class

I have a case, where I have an instance of a class in python which holds instances of other classes. For my use case, I would like a way to use the methods of the "inner" classes from the outer class without referencing the attribute holding the inner class.

I have made a simplistic example here:

class A:
    def __init__(self):
        pass

    def say_hi(self):
        print("Hi")

    def say_goodbye(self):
        print("Goodbye")


class C:
    def __init__(self, other_instance):
        self.other_instance= other_instance

    def say_good_night(self):
        print("Good night")

my_a = A()
my_c = C(other_instance=my_a)

# How to make this possible:
my_c.say_hi()

# Instead of
my_c.other_instance.say_hi()

Class inheritance is not possible, as the object passed to C may be an instance of a range of classes. Is this possible in Python?

Upvotes: 1

Views: 95

Answers (2)

S.B
S.B

Reputation: 16486

I think this is the simplest solution although it is possible with metaprogramming.

class A:
    def __init__(self):
        pass

    def say_hi(self):
        print("Hi")

    def say_goodbye(self):
        print("Goodbye")


class C:
    def __init__(self, other_class):
        self.other_class = other_class
        C._add_methods(other_class)

    def say_good_night(self):
        print("Good night")

    @classmethod
    def _add_methods(cls, obj):
        type_ = type(obj)
        for k, v in type_.__dict__.items():
            if not k.startswith('__'):
                setattr(cls, k, v)


my_a = A()
my_c = C(other_class=my_a)

my_c.say_hi()

output :

Hi

First we get the type of passed instance, then we iterate through it's attribute (because methods are attributes of the class not the instance).

If self.other_class is only needed for this purpose, you can omit it as well.

Upvotes: 2

Salaah Amin
Salaah Amin

Reputation: 452

So, because you have done: my_a = A() and my_c = C(other_class=my_a). my_c.other_class is the same as my_a asthey point to the same location in memory.

Therefore, as you can do my_a.say_hi() you could also do my_c.other_class.say_hi().

Also, just a note, as you are calling A() before you store it into other_classes, I would probably rename the variable other_classes to class_instances.

Personally, I think that would make more sense, as each of those classes would have already been instantiated.

Upvotes: 0

Related Questions