python - 如何避免python中的并行类层次结构
问题描述
我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
习惯层次结构中很有用,但在狗层次结构中没有用,因为我需要为狗层次结构中的每个类实例化一个单独的习惯对象。
这有什么解药?我可能想添加很多狗类的实现,更新相应的习惯层次结构听起来很乏味,而且闻起来很糟糕......
解决方案
这可能太过分了,但我认为不需要单独的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
推荐阅读
- window - 任何强制无边框应用显示边框的方法
- php - 使用会话变量重定向到另一个页面时,php 警报不起作用
- ssl - JMeter http 采样器在 ssl.AppInputStream.read() 方法中花费时间
- python - Numpy:测试一个数组项目是否高于某个值,x连续次数?
- c# - 夏令时导致 highcart 出现问题
- laravel - 双查询构建器关系表中带有行代码的 Laravel 错误
- python - 基于数据的matplotlib自动缩放轴出现在图中
- r - R,代码在没有 for 循环的情况下工作,但不在循环内
- ios - (SWIFT 4)如何计算 tableview 中列 indexpath.row 的总和?
- apache - content-security-policy 正在阻止我需要的内容