首页 > 解决方案 > 从类实例动态继承并将类型更改为新创建的类

问题描述

假设我有 2 个(或更多)动物类,猫和狗,它们都是需要sound方法的 ABC 动物类的子类。

假设我想创建一个方法,将 Cat 或 Dog 的实例修改为 SuperCat 或 SuperDog 类的新实例,保留实例的初始化属性,但修改 sound 方法(使其调用大写)。Cat 和 Dog 具有不同的初始化和属性。

我目前通过在运行时动态创建类然后复制实例并更改其内部__class__属性来实现这一点。

这感觉像是在作弊。处理此类问题的pythonic方式是什么?

库代码:

from abc import ABC, abstractmethod
from copy import deepcopy

class Animal(ABC):

    @abstractmethod
    def sound(self):
        pass

class Cat(Animal):

    def __init__(self,favorite_catnip="BrandName"):
        self.favorite_catnip = favorite_catnip

    def sound(self):
        return "purr"

class Dog(Animal):

    def __init__(self,best_friend="Human"):
        self.best_friend = best_friend

    def sound(self):
        return "woof"


def createSuperAnimal(animal):
    # Check that we at least got an animal
    if not isinstance(animal,Animal):
        raise TypeError("Given class instance needs to be an animal")

    # Dynamically create new super animal class with loud sounds!
    class SuperAnimal(type(animal)):
        # Super animals have loud sounds
        def sound(self):
            return super().sound().upper()

    # Make a copy of existing instance and change its class
    # This gets us the initialized values for the Cat or Dog.
    superAnimal = deepcopy(animal)
    superAnimal.__class__ = SuperAnimal
    return superAnimal

示例调用:

# initialize the two distinct sub-classes
dog = Dog()
cat = Cat()
print(dog.sound())
print(cat.sound())

# Create super animals
superDog = createSuperAnimal(dog)
superCat = createSuperAnimal(cat)
print(superDog.sound())
print(superCat.sound())

# Superdog has best friend, superCat has favorite_catnip
print(superDog.best_friend)
print(superCat.favorite_catnip)

输出:

woof
purr
WOOF
PURR
Human
BrandName

标签: pythonclassinheritance

解决方案


推荐阅读