我想要使用几个子类,但是它们都从父级继承了一个方法,并不像我需要的那样。
class ParentClass():
def __init__(self, value):
self.value = value
def annoying_funct(self):
print("I don't do quite what's needed and print {0}".format(self.value + 1))
def other_parent(self):
print("I do other useful things my children inherit")
class Child1(ParentClass):
def __init__(self, value, new_value1):
super(Child1, self).__init__(value)
self.new_value1 = new_value1
def other_child1(self):
print("I do useful child things")
class Child2(ParentClass):
def __init__(self, value, new_value2):
super(Child2, self).__init__(value)
self.new_value2 = new_value2
def other_child2(self):
print("I do other useful child things")
我想覆盖annoying_funct()
,如下所示:
def annoying_funct():
print("I behave the way I am needed to and print {0}".format(self.value))
ParentClass
,Child1
和Child2
来自一个非常复杂的库(scikit-learn
),因此我希望尽可能地保留所有包装器。什么是最干净/最pythonic的方式来获得我的两个子类的功能,同时根据需要改变父类?
到目前为止我的想法:
创建一个继承自父级的新类,该类覆盖我不喜欢的函数,然后为从新类和子类继承的子级创建包装类。
class NewParentClass(ParentClass):
def annoying_funct(self):
print("I behave the way I am needed to and print {0}".format(self.value))
class NewChild1(NewParentClass, Child1):
pass
class NewChild2(NewParentClass, Child2):
pass
我的困惑之处:
parentClass
和newParentClass
之间继承的子项运行(例如def newParentClass():
),但如果有人试图创建newParentClass()
的实例,则该函数将不会; t工作,因为它使用该类中不存在的属性(value
)。如果我认为该课程永远不会被使用,那可以吗?答案 0 :(得分:0)
有几种方法可以做你要求的。
此解决方案的唯一缺点是,当您向需要原始Parent类的函数提供新的父类或子类时,可能无法正常工作,因为它们可能使用annoying_funct
并依赖于恼人的行为。
class NewParentClass:
def annoying_funct(self):
print("I behave the way I am needed to and print {0}".format(self.value))
class NewChild1(NewParentClass):
pass
class NewChild2(NewParentClass):
pass
这是我想要使用的解决方案,因为它通过将其替换为行为良好的annoying_funct
完全销毁,再次购买,需要前annoying_funct
的其他方法和功能可能会失败。好的一面是,您不需要创建另一个父类和子代,因此您的代码将更加优雅。
class ParentClass():
...
def annoying_funct(self):
print("I don't do quite what's needed and print {0}".format(self.value + 1))
...
def well_behaving_func(s):
print("Good")
# Dynamically change the class method
ParentClass.annoying_func = well_behaving_func
class Child1(Parent):
pass
class Child2(Parent):
pass
c = Child1()
c.annoying_funct() # prints 'Good'
如果您想维护当前行为并且不希望现有代码或包依赖于父类中断,那么您当然不应该覆盖父类中的annoying_funct
。所以你应该定义一个行为良好的函数并在子类中使用它。
class ParentClass():
...
def annoying_funct(self):
print("I don't do quite what's needed and print {0}".format(self.value + 1))
...
def well_behaving_func(s):
print("Good")
# Dynamically change the class method
ParentClass.well_behaving_func = well_behaving_func
class Child1(Parent):
pass
class Child2(Parent):
pass
c = Child1()
# use 'well_behaving_func', not the annoying one
c.well_behaving_func() # prints 'Good'
答案 1 :(得分:0)
我最终做的是使用mixin的概念将我的新功能添加到子类。结果代码如下:
class AnnoyMixin:
def well_behaving_func(self):
print("I behave the way I am needed to and print {0}".format(self.value))
class NewChild1(AnnoyMixin, Child1):
def annoying_funct(self):
return well_behaving_func(self)
class NewChild2(AnnoyMixin, Child2):
def annoying_funct(self):
return well_behaving_func(self)
从功能上讲,这与我在我的问题中提出的代码大致相同,但这些修改有助于提高可读性。首先,通过将新父命名为“Mixin”,它清楚地表明该类不是为了独立而设计,而是为了向另一个类添加功能。因此,AnnoyMixin
不需要从ParentClass
继承,从而简化了NewChild
类的继承。
其次,我们创建新函数annoying_funct
,而不是覆盖AnnoyMixin
中的well_behaving_func
。然后通过调用NewChild
来覆盖annoying_funct
well_behaving_func
类作业。从功能上讲,这与AnnoyMixin
覆盖annoying_funct
的工作方式大致相同,但这样,读取annoying_funct
被覆盖NewChild
的代码更加清晰。 {1}}课程。