How to avoid parallel class hierarchy in python

前端 未结 3 1813
太阳男子
太阳男子 2021-01-21 04:19

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 concoc

3条回答
  •  春和景丽
    2021-01-21 04:46

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

    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)
    

    output:

    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']
    

提交回复
热议问题