亚洲在线久爱草,狠狠天天香蕉网,天天搞日日干久草,伊人亚洲日本欧美

為了賬號安全,請及時綁定郵箱和手機立即綁定
已解決430363個問題,去搜搜看,總會有你想問的

如何避免 python 中的并行類層次結構

如何避免 python 中的并行類層次結構

小唯快跑啊 2022-12-20 16:11:46
我python最近在我的代碼中遇到了一種奇怪的小味道,我認為它與并行繼承有關。這是我編造的一個小例子: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()我有一個通用的狗類,具體的狗實現從中繼承。每個狗類(包括通用/抽象類)都有一組習慣,它們本身由習慣的另一個類層次結構表示。令我惱火的是,我必須始終讓兩個層次結構完全相同。此外, 之間的繼承在DogHabits習慣層次結構中很有用,但在狗層次結構中沒有用,因為我需要為狗層次結構中的每個類實例化一個單獨的習慣對象。什么是解毒劑?我可能想添加狗類的許多實現,更新相應的習慣層次結構聽起來很乏味而且聞起來很糟糕......
查看完整描述

3 回答

?
ITMISS

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


查看完整回答
反對 回復 2022-12-20
?
慕的地8271018

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


查看完整回答
反對 回復 2022-12-20
?
白板的微信

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


查看完整回答
反對 回復 2022-12-20
  • 3 回答
  • 0 關注
  • 113 瀏覽
慕課專欄
更多

添加回答

舉報

0/150
提交
取消
微信客服

購課補貼
聯系客服咨詢優惠詳情

幫助反饋 APP下載

慕課網APP
您的移動學習伙伴

公眾號

掃描二維碼
關注慕課網微信公眾號