如何避免python中的并行类层次结构 [英] How to avoid parallel class hierarchy in python

查看:105
本文介绍了如何避免python中的并行类层次结构的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我最近在python代码中遇到了一种奇怪的气味,我认为这与并行继承有关.这是我炮制的一个小例子:

I've been running into a weird little smell in my python code lately and I think it has something to do with parallel inheritance. Here is a small example I concocted:

class DogHabits:
    def __init__(self):
        self.habits = ['lick butt']

class GermanShepherdHabits(DogHabits):
    def __init__(self):
        super().__init__()
        self.habits.extend(['herd sheep'])

class LabradorHabits(DogHabits):
    def __init__(self):
        super().__init__()
        self.habits.extend(['hunt', 'pee on owner'])

class Dog:
    def __init__(self):
        self.type = 'generic_dog'
        self.my_habits = DogHabits()

    def do_stuff(self):
        for habit in self.my_habits.habits:
            print(habit)

class GermanShepherd(Dog):
    def __init__(self):
        self.type = 'german shepherd'
        self.my_habits = GermanShepherdHabits()

class Labrador(Dog):
    def __init__(self):
        self.type = 'labrador'
        self.my_habits = LabradorHabits()

if __name__ == "__main__":
    german_shepherd = GermanShepherd()
    print('\n{}'.format(german_shepherd.type))
    german_shepherd.do_stuff()


    labrador = Labrador()
    print('\n{}'.format(labrador.type))
    labrador.do_stuff()

我有一个通用的狗类,具体的狗实现从中继承.每个犬类(包括通用/抽象犬类)都有一套习惯,而习惯本身又由另一种等级构成.

I have a generic dog class from which concrete dog implementations inherit. Every dog class (including the generic/abstract one) has a set of habits, itself represented by another class hierarchy for the habits.

我必须始终拥有两个完全相同的层次结构,这使我感到恼火.此外,DogHabits之间的继承在习惯层次结构中很有用,但在狗层次结构中却没有用,因为我需要为狗层次结构中的每个类实例化一个单独的习惯对象.

I am annoyed by the fact that I have to have both hierarchies exactly the same at all times. Furthermore the inheritance between the DogHabits is useful within the habits hierarchy, but it is not useful within the dogs hierarchy, as I need to instantiate a separate habits object for each class in the dog hierarchy.

此药的解毒剂是什么?我可能要添加dog类的许多实现,并更新相应的习惯层次结构听起来很乏味,而且味道很差.

What is the antidote to this? I may want to add many implementations of the dog class, and updating the corresponding habits hierarchy sounds tedious and smells bad...

推荐答案

如果习惯需要一个类属性,而不是实例属性,那么可能实际上是一个好习惯用于元类.

IF habits need to a class attribute, rather than instance attributes, this may actually be a good use for metaclasses.

习惯不必是一个简单的列表,也可以是其他列表,只要在前一个概念上有加法,然后返回新值即可. (习惯类上的__add____radd__可以解决我的问题)

Habits need not be a simple list, it could be something else, as long as there is the notion of addition to previous and return new. (__add__ or __radd__ on a Habits class would do the trick I think)

class DogType(type):

    def __init__(cls, name, bases, attrs):
        """ this is called at the Dog-class creation time.  """

        if not bases:
            return

        #pick the habits of direct ancestor and extend it with 
        #this class then assign to cls.
        if "habits" in attrs:
            base_habits = getattr(bases[0], "habits", [])
            cls.habits = base_habits + cls.habits


class Dog(metaclass=DogType):
    habits = ["licks butt"]

    def __repr__(self):
        return f"My name is {self.name}.  I am a {self.__class__.__name__} %s and I like to {self.habits}"

    def __init__(self, name):
        """ dog instance can have all sorts of instance variables"""
        self.name = name

class Sheperd(Dog):
    habits = ["herds sheep"]

class GermanSheperd(Sheperd):
    habits = ["bites people"]

class Poodle(Dog):
    habits = ["barks stupidly"]

class StBernard(Dog):
    pass


for ix, cls in enumerate([GermanSheperd, Poodle, StBernard]):
    name = f"dog{ix}"
    dog = cls(name)
    print(dog)

输出:

My name is dog0.  I am a GermanSheperd %s and I like to ['licks butt', 'herds sheep', 'bites people']
My name is dog1.  I am a Poodle %s and I like to ['licks butt', 'barks stupidly']
My name is dog2.  I am a StBernard %s and I like to ['licks butt']

这篇关于如何避免python中的并行类层次结构的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆