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')
添加回答
舉報