Преобразование дочернего объекта в родительский Python
Есть 2 класса:
class MyClass:
def A(self):
print(1)
class YourClass(MyClass):
def A(self):
print(2)
Метод A базового класса выводит на консоль число 1. Наследник переопределяет данный метод и выводит на консоль 2. Если в коде создать объект класса YourClass и вызвать у него метод A, то в выводе будет 2:
your_class = YourClass()
your_class.A() # 2
Задача дана следующая: Реализовать преобразование дочернего объекта в родительский. После этого преобразования (не изменяя реализации метода A в классе YourClass) при вызове метода A для объекта класса YourClass, выводить в консоль уже должно не 2, а 1. Т.е. :
your_class = YourClass()
your_class.A() # 1
Помогите пожалуйста решить данную задачу, никак не могу прийти к решению.
Ответы (3 шт):
Обычно так не делают, вместо этого создают новый объект нужного класса на основе существующего. Можно написать метод или функцию, который быдет принимать объект одного типа и на его основе конструировать объект другого типа.
Но если уж прямо очень хочется изменить класс имеющегося объекта, то так:
class MyClass:
def A(self):
print(1)
class YourClass(MyClass):
def A(self):
print(2)
your_class = YourClass()
your_class.A() # 2
your_class.__class__ = MyClass
your_class.A() # 1
Только сразу предупреждаю, что это очень тёмная магия, чреватая разными спецэффектами и в реальном коде так делать не стоит.
Можно добавить статический метод к классу MyClass, который будет преобразовывать YourClass в MyClass. Правда, в данном примере преобразований по-факту не будет.
# @name 66b260a0cf9845989b9d21c897fe9b1a.py
class MyClass:
def A(self):
print(1)
@staticmethod
def CastFromYourClass(src):
'''Преобразует YourClass в MyClass.
Параметр src Экземпляр класса YourClass.
Возвращает экземпляр класса MyClass.
'''
if not isinstance(src, YourClass):
raise TypeError("Параметр src не YourClass.")
instance = MyClass()
# Здесь различные преобразования.
# Например, instance.data = src.data.lower()
return instance
class YourClass(MyClass):
def A(self):
print(2)
src = YourClass()
instance = MyClass.CastFromYourClass(src) # Преобразуем YourClass в MyClass.
instance.A()
print(type(instance)) # instance - MyClass
Можно это же сделать в инициализаторе класса MyClass, но придется заморачиваться с перегрузкой параметров инициализатора.
Если хотите также, как и у вас, то вот еще один вариант:
class MyClass:
def A(self):
print(1)
class YourClass(MyClass):
def __new__(_cls):
return object.__new__(MyClass)
def A(self):
print(2)
your_class = YourClass()
your_class.A() # 1
Вот только экземпляры класса YourClass теперь невозможно будет получить адекватным способом, и это даже не преобразование из одного экземпляра в другой.
Можно сделать monkey patching такого вида, переназначив метод через __setattr__ внутри объекта, к примеру.
class MyClass:
def A(self):
print(1)
class YourClass(MyClass):
def A(self):
print(2)
your_class = YourClass()
# Вариант 1
your_class.__setattr__('A', MyClass().A)
your_class.A() # 1
# Или вариант 2
your_class.A = MyClass().A
your_class.A() # 1