使用一组方法和属性(包装器)扩展独立 类

Extend independent classes with a set of methods and attributes (wrapper)

我的目标是创建一个 class 来扩展具有一组功能的不同 classes。 在下面的代码中,我能够创建问题的解决方案,但对我来说,这似乎不是解决问题的方法。

要求:
- 基础 classes (Cat, Dog) 不能改变。
- 具有附加功能(Pet_Dog、Pet_Cat)的 classes 应该具有最少的代码量,因为我需要很多代码,只需稍作改动。
- 我需要能够导入 BaseClasses (Cat, Dog) 以及增强的 class (Pet_Dog, Pet_Cat).

我的 "solution" 到目前为止:

class Cat:
    def __init__(self, legs):
        self.legs = 4
        self.lives = 9

    def make_sound(self):
        print('Meow!')

class Dog:
    def __init__(self, legs):
        self.legs = 4
        self.hobby = 'Digging holes'

    def make_sound(self):
        print('Woof!')

    def chase_tail(self):
        print('Chasing tail')

def create_pet(BaseClass):
    class Pet(BaseClass):
        has_owner = True
        def __init__(self, name, legs):
            super().__init__(legs)
            self.name = name

        def plays_with_owner(self):
            print('playing with owner...')
    return Pet


class Pet_Dog(Dog):
    def __init__(self, BaseClass, name, legs):
        self.__class__ = create_pet(BaseClass)(name, legs).__class__
        self.__init__(name, legs)


class Pet_Cat(Cat):
    def __init__(self, BaseClass, name, legs):
        self.__class__ = create_pet(BaseClass)(name, legs).__class__
        self.__init__(name, legs)


print('Create Pet Dog')
pet_dog = Pet_Dog(Dog, 'Woofer', 4)
print('Dog Name:', pet_dog.name)
print('Dog Lives:', pet_dog.hobby)
print('Dog Owner:', pet_dog.has_owner)
pet_dog.make_sound()
pet_dog.chase_tail()
pet_dog.plays_with_owner()

在 Python 中,您可以拥有继承自多个其他 class 的 class,因此我们可以制作 CatDog class,以及单独的Pet class。然后我们可以让 Pet_CatPet_Dog 继承自 Pet 和它们各自的动物,即:

class Cat:
    def __init__(self, legs):
        self.legs = legs
        self.lives = 9

    def make_sound(self):
        print('Meow!')

class Dog:
    def __init__(self, legs):
        self.legs = legs
        self.hobby = 'Digging holes'

    def make_sound(self):
        print('Woof!')

    def chase_tail(self):
        print('Chasing tail')

class Pet:
    has_owner = True
    name = None

    def plays_with_owner(self):
        print('playing with owner...')

class Pet_Dog(Dog, Pet):
    def __init__(self, name, legs):
        super().__init__(legs)
        self.name = name

class Pet_Cat(Cat, Pet):
    def __init__(self, name, legs):
        super().__init__(legs)
        self.name = name


print('Create Pet Dog')
pet_dog = Pet_Dog('Woofer', 4)
print('Dog Name:', pet_dog.name)
print('Dog Lives:', pet_dog.hobby)
print('Dog Owner:', pet_dog.has_owner)
pet_dog.make_sound()
pet_dog.chase_tail()
pet_dog.plays_with_owner()

输出:

Create Pet Dog
Dog Name: Woofer
Dog Lives: Digging holes
Dog Owner: True
Woof!
Chasing tail
playing with owner...

编辑:

如果你想在两者上都使用 init 函数,请改用它:

class Cat:
    def __init__(self, legs):
        self.legs = legs
        self.lives = 9

    def make_sound(self):
        print('Meow!')

class Dog:
    def __init__(self, legs):
        self.legs = legs
        self.hobby = 'Digging holes'

    def make_sound(self):
        print('Woof!')

    def chase_tail(self):
        print('Chasing tail')

class Pet:
    def __init__(self):
        self.has_owner = True
        self.name = None

    def plays_with_owner(self):
        print('playing with owner...')

class Pet_Dog(Dog, Pet):
    def __init__(self, name, legs):
        Dog.__init__(self, legs)
        Pet.__init__(self)

        self.name = name

class Pet_Cat(Cat, Pet):
    def __init__(self, name, legs):
        Cat.__init__(self, legs)
        Pet.__init__(self)

        self.name = name

如果你真的想在这里使用继承,可以使用多重继承和协同super调用来避免无用的重复:

class Cat:
    def __init__(self, legs):
        self.legs = legs
        self.lives = 9


class Dog:
    def __init__(self, legs):
        self.legs = legs
        self.hobby = 'Digging holes'

class Pet:
    def __init__(self, name, *args, **kwargs):
        self.has_owner = True
        self.name = name
        super().__init__(*args, **kwargs)

    def plays_with_owner(self):
        print('playing with owner...')


# Pet has to come before the "animal" class for the cooperative
# super() call to work

class PetCat(Pet, Cat):
    pass

class PetDog(Pet, Dog):
    pass

您甚至可以自动创建这些子类,但这不一定是一种改进:

def make_pet_class(name, base):
    return type.__new__(name, (Pet, base), {})

PetCat = make_pet_class("PetCat", Cat)

现在继承不一定是解决所有问题的最佳方案。继承主要是一种非常受限的组合/委托形式,Python 使组合/委托非常容易:

class Pet:
    def __init__(self, name, animal):
        self._animal  = animal
        self.name = name
        self.has_owner = True

    def plays_with_owner(self):
        print('playing with owner...')

    def __getattr__(self, attr):
        return getattr(self._animal, attr)


kitty = Pet("kitty", Cat(4))
pluto = Pet("pluto", Dog(4))