如何从 Python 中的子 class 调用和覆盖父 class 方法
How to call and override a Parent class method from Child class in Python
在 ResistantVirus
class 的 reproduce
方法中,我试图调用 SimpleVirus
class 的 reproduce(self, popDensity)
,但是相反return 一个 SimpleVirus
对象,我希望它 return 一个 ResistantVirus
对象。
显然,我也可以重复 SimpleVirus.reproduce
方法中的一些代码并在我的 ResistantVirus.reproduce
方法中使用相同的实现,但我想知道是否可以调用和覆盖 SimpleVirus.reproduce
为了避免重复?
class SimpleVirus(object):
def __init__(self, maxBirthProb, clearProb):
self.maxBirthProb = maxBirthProb
self.clearProb = clearProb
def reproduce(self, popDensity):
if random.random() > self.maxBirthProb * (1 - popDensity):
raise NoChildException('In reproduce()')
return SimpleVirus(self.getMaxBirthProb(), self.getClearProb())
class ResistantVirus(SimpleVirus):
def __init__(self, maxBirthProb, clearProb, resistances, mutProb):
SimpleVirus.__init__(self, maxBirthProb, clearProb)
self.resistances = resistances
self.mutProb = mutProb
def reproduce(self, popDensity)
## returns a new instance of the ResistantVirus class representing the
## offspring of this virus particle. The child should have the same
## maxBirthProb and clearProb values as this virus.
## what I sketched out so far and probs has some mistakes:
for drug in activeDrugs:
if not self.isResistantTo(drug):
raise NoChildException
break
simple_virus = SimpleVirus.reproduce(self,popDensity)
return ResistantVirus(simple_virus.getMaxBirthProb(),simple_virus.getClearProb())
使用super调用父class'方法:
class ResistantVirus(SimpleVirus):
def __init__(self, maxBirthProb, clearProb, resistances, mutProb):
self.resistances = resistances
self.mutProb = mutProb
super(ResistantVirus, self).__init__(maxBirthProb, clearProb)
def reproduce(self, popDensity):
simple_virus = super(ResistantVirus, self).reproduce(popDensity)
resistances = # TODO
mutProb = # TODO
return ResistantVirus(simple_virus.maxBirthProb,
simple_virus.clearProb,
resistances,
mutProb)
看来 copy
可以帮到你。
import copy
class Parent(object):
def __init__(self, a):
self.a = a
def copy(self):
return copy.deepcopy(self)
class Child(Parent):
def __init__(self, a, b):
super(Child, self).__init__(a)
self.b = b
copy 方法将携带任何 self
的 class(不一定是 Parent)。例如:
Child(1,2).copy() # <__main__.Child object at 0x01832E90>
这似乎是您的主要目标。但是,在如何构建测试方面也可能值得付出一些努力。我已经使用您的示例代码实现了一个不同的解决方案,允许您继承测试。请注意,这要求您向病毒传递一个关键字参数列表 (**kwargs
)。后面给出了示例用法。
import copy, random
class SimpleVirus(object):
def __init__(self, max_birth_prob, clear_prob):
self.max_birth_prob = max_birth_prob
self.clear_prob = clear_prob
self._tests = [self.simple_test]
def copy(self):
return copy.deepcopy(self)
def simple_test(self, **kwargs):
return random.random() < self.max_birth_prob * (1 - kwargs['pop_density'])
def reproduce(self, **kwargs):
if all(test(**kwargs) for test in self._tests):
return self.copy()
raise Exception
class ResistantVirus(SimpleVirus):
def __init__(self, max_birth_prob, clear_prob, resistances, mut_prob):
super(ResistantVirus, self).__init__(max_birth_prob, clear_prob)
self.resistances = resistances
self.mut_prob = mut_prob
self._tests.append(self.resistance_test)
def resistance_test(self, **kwargs):
return all(drug in self.resistances for drug in kwargs['drug_list'])
以下内容有时会重现,有时会引发 Exception
。
res_virus = ResistantVirus(0.8, 0.2, ['a', 'b', 'c'], 0.1)
res_virus.reproduce(pop_density=0.3, drug_list=['a', 'b'])
请注意,两个 classes 之间没有明显的代码重用。如果你有一个严格的继承链并且事情趋于 "build-up" 这很好。但是,如果您要有很多 classes 都继承 SimpleVirus
,并且其中一些 classes 共享功能,那么 object composition over inheritance 可能值得一看.
只要 __init__()
签名兼容,您就可以使用实例的类型而不是显式类型。
class Parent(object):
def __str__(self):
return 'I am a Parent'
def reproduce(self):
# do stuff common to all subclasses.
print('parent reproduction')
# then return an instance of the caller's type
return type(self)()
class Child(Parent):
def __str__(self):
return 'I am a Child'
def reproduce(self):
# do stuff specific to Child.
print('child reproduction')
# call the parent's method but it will return a
# Child object
return super(Child, self).reproduce()
print(Parent().reproduce())
parent reproduction
I am a Parent
print(Child().reproduce())
child reproduction
parent reproduction
I am a child
在 ResistantVirus
class 的 reproduce
方法中,我试图调用 SimpleVirus
class 的 reproduce(self, popDensity)
,但是相反return 一个 SimpleVirus
对象,我希望它 return 一个 ResistantVirus
对象。
显然,我也可以重复 SimpleVirus.reproduce
方法中的一些代码并在我的 ResistantVirus.reproduce
方法中使用相同的实现,但我想知道是否可以调用和覆盖 SimpleVirus.reproduce
为了避免重复?
class SimpleVirus(object):
def __init__(self, maxBirthProb, clearProb):
self.maxBirthProb = maxBirthProb
self.clearProb = clearProb
def reproduce(self, popDensity):
if random.random() > self.maxBirthProb * (1 - popDensity):
raise NoChildException('In reproduce()')
return SimpleVirus(self.getMaxBirthProb(), self.getClearProb())
class ResistantVirus(SimpleVirus):
def __init__(self, maxBirthProb, clearProb, resistances, mutProb):
SimpleVirus.__init__(self, maxBirthProb, clearProb)
self.resistances = resistances
self.mutProb = mutProb
def reproduce(self, popDensity)
## returns a new instance of the ResistantVirus class representing the
## offspring of this virus particle. The child should have the same
## maxBirthProb and clearProb values as this virus.
## what I sketched out so far and probs has some mistakes:
for drug in activeDrugs:
if not self.isResistantTo(drug):
raise NoChildException
break
simple_virus = SimpleVirus.reproduce(self,popDensity)
return ResistantVirus(simple_virus.getMaxBirthProb(),simple_virus.getClearProb())
使用super调用父class'方法:
class ResistantVirus(SimpleVirus):
def __init__(self, maxBirthProb, clearProb, resistances, mutProb):
self.resistances = resistances
self.mutProb = mutProb
super(ResistantVirus, self).__init__(maxBirthProb, clearProb)
def reproduce(self, popDensity):
simple_virus = super(ResistantVirus, self).reproduce(popDensity)
resistances = # TODO
mutProb = # TODO
return ResistantVirus(simple_virus.maxBirthProb,
simple_virus.clearProb,
resistances,
mutProb)
看来 copy
可以帮到你。
import copy
class Parent(object):
def __init__(self, a):
self.a = a
def copy(self):
return copy.deepcopy(self)
class Child(Parent):
def __init__(self, a, b):
super(Child, self).__init__(a)
self.b = b
copy 方法将携带任何 self
的 class(不一定是 Parent)。例如:
Child(1,2).copy() # <__main__.Child object at 0x01832E90>
这似乎是您的主要目标。但是,在如何构建测试方面也可能值得付出一些努力。我已经使用您的示例代码实现了一个不同的解决方案,允许您继承测试。请注意,这要求您向病毒传递一个关键字参数列表 (**kwargs
)。后面给出了示例用法。
import copy, random
class SimpleVirus(object):
def __init__(self, max_birth_prob, clear_prob):
self.max_birth_prob = max_birth_prob
self.clear_prob = clear_prob
self._tests = [self.simple_test]
def copy(self):
return copy.deepcopy(self)
def simple_test(self, **kwargs):
return random.random() < self.max_birth_prob * (1 - kwargs['pop_density'])
def reproduce(self, **kwargs):
if all(test(**kwargs) for test in self._tests):
return self.copy()
raise Exception
class ResistantVirus(SimpleVirus):
def __init__(self, max_birth_prob, clear_prob, resistances, mut_prob):
super(ResistantVirus, self).__init__(max_birth_prob, clear_prob)
self.resistances = resistances
self.mut_prob = mut_prob
self._tests.append(self.resistance_test)
def resistance_test(self, **kwargs):
return all(drug in self.resistances for drug in kwargs['drug_list'])
以下内容有时会重现,有时会引发 Exception
。
res_virus = ResistantVirus(0.8, 0.2, ['a', 'b', 'c'], 0.1)
res_virus.reproduce(pop_density=0.3, drug_list=['a', 'b'])
请注意,两个 classes 之间没有明显的代码重用。如果你有一个严格的继承链并且事情趋于 "build-up" 这很好。但是,如果您要有很多 classes 都继承 SimpleVirus
,并且其中一些 classes 共享功能,那么 object composition over inheritance 可能值得一看.
只要 __init__()
签名兼容,您就可以使用实例的类型而不是显式类型。
class Parent(object):
def __str__(self):
return 'I am a Parent'
def reproduce(self):
# do stuff common to all subclasses.
print('parent reproduction')
# then return an instance of the caller's type
return type(self)()
class Child(Parent):
def __str__(self):
return 'I am a Child'
def reproduce(self):
# do stuff specific to Child.
print('child reproduction')
# call the parent's method but it will return a
# Child object
return super(Child, self).reproduce()
print(Parent().reproduce())
parent reproduction
I am a Parent
print(Child().reproduce())
child reproduction
parent reproduction
I am a child