3 回答
TA贡献1871条经验 获得超8个赞
这可能走得太远了,但我认为不需要单独的DogHabits课程。habits应该是类属性,而不是实例属性,并且可以由__init_subclass__.
class Dog:
habits = ['lick butts']
def __init_subclass__(cls, habits=None, **kwargs):
super().__init_subclass__(**kwargs)
if habits is not None:
cls.habits = cls.habits + habits
class GermanShepherd(Dog, habits=['herd sheep']):
def __init__(self):
self.type = 'german shepherd'
class Labrador(Dog, habits=['pee on owner']):
def __init__(self):
self.type = 'labrador'
type本身也更像是一个类属性而不是实例属性,因为它只是已经由类本身编码的信息的(替代)字符串表示。由于您不会附加到现有值,因此只需在必要时设置类属性而不是通过__init_subclass:
class Dog:
habits = ['lick butts']
type = 'generic_dog'
def __init_subclass__(cls, habits=None, **kwargs):
super().__init_subclass__(**kwargs)
if habits is not None:
cls.habits = cls.habits + habits
class GermanShepherd(Dog, habits=['herd sheep']):
type = 'german shepard'
class Labrador(Dog, habits=['pee on owner']):
type = 'labrador'
class BlackLabrador(Labrador):
pass # E.g. if you are happy with inheriting Labrador.type
TA贡献1796条经验 获得超4个赞
如果习惯需要一个类属性,而不是实例属性,这实际上可能是元类的一个很好的用途。
习惯不一定是一个简单的列表,它可以是其他东西,只要有加法和返回新的概念即可。(__add__或者__radd__在习惯课上我认为可以做到这一点)
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']
TA贡献1883条经验 获得超3个赞
这个答案假设 DogHabits 比单纯的列表复杂得多,并且确实值得一个具有自己继承的专用类。
从设计的角度来看,我可以看到第一个问题是是否habits以及type应该是类成员还是实例成员。同样,这个答案假设有理由让他们成为实例成员。
我会在类文档中创建Habits一个内部类Dogs并声明它可以通过在以下子类中构建它的子类来定制Dogs:
class Dog:
class Habits:
"""Represents the habits of a Dog.
It can be customized in a child class by creating in the subclass an
inner class named Habits that would be a subclass of Dog.Habits
"""
def __init__(self):
self.habits = ['lick butt']
def __init__(self, typ='generic_dog'):
self.type = typ
self.my_habits = self.__class__.Habits()
def do_stuff(self):
for habit in self.my_habits.habits:
print(habit)
class GermanShepherd(Dog):
class Habits(Dog.Habits):
def __init__(self):
super().__init__()
self.habits.extend(['herd sheep'])
def __init__(self):
super().__init__('german shepherd')
class Labrador(Dog):
class Habits(Dog.Habits):
def __init__(self):
super().__init__()
self.habits.extend(['hunt', 'pee on owner'])
def __init__(self):
super().__init__('labrador')
添加回答
举报