在python中如何防止父类的实例变量被子类覆盖?

2024-06-09 04:43:52 发布

您现在位置:Python中文网/ 问答频道 /正文

我有两个非常简单的类写在下面。HumanMammal类继承。当我调用print(jo.drinkMe("sage"))时,我希望打印“sick”,但打印“fine”。我认为Human类中的self.problem覆盖了Mammal类中的self.problem。为了让最后的print语句打印“sick”,我需要对代码做些什么?你知道吗

class Mammal:
    def __init__(self):
        self.problem = "sage"
        self.result = "sick"

    def drinkMe(self,tea):
        if tea == self.problem:
            return self.result
        else:
            return "fine"

class Human(Mammal):
    def __init__(self):
        super().__init__()
        self.problem = "paint"
        self.result = "die"
    def drinkMe(self,tea):
        if tea == self.problem:
            return self.result
        else:
            return super().drinkMe(tea)

jo = Human()
to = Mammal()
print(jo.drinkMe("sage"))

Tags: selfreturninitdefresultprintproblemsage
3条回答

我发现了一种非常简单的方法来防止在Human中声明的实例变量重写在Mammal中声明的实例变量。每次调用drink_me时,代码基本上只是重新分配self.problemself.result的值:

class Mammal:

    def __init__(self):
        self.problem = "sage"
        self.result = "sick"

    def drinkMe(self,tea):
        if tea == self.problem:
            return self.result
        else:
            return "fine"
class Human(Mammal):
    def __init__(self):
        super().__init__()
        self.problem = "paint"
        self.result = "die"
    def drinkMe(self,tea):
        result = ''
        if tea == self.problem:
            return self.result
        else:
            super().__init__()
            result = super().drinkMe(tea)
            self.__init__()
            return(result)
jo = Human()
print(jo.drinkMe("sage"))
print(jo.drinkMe("paint"))

这个代码先打印“生病”,然后打印“死亡”。你知道吗

问题是Mammal在实例化时只设置它的实例属性problemresultjo = Human()实例化Mammal对象,然后将problemresult属性合并到自己的对象中。详细地说,您必须:

class Human(Mammal):
    def __init__(self):
        super().__init__()
        # calls `Mammal.__init__()`, which sets
        # self.problem = "sage"
        # self.result = "sick"
        self.problem = "paint"
        self.result = "die"
        # overwrites what `Mammal.__init__()` did a
        # couple lines ago.
   ...

您可以改为:

class Mammal(object):
    problem = "sage"
    result = "sick"

    def drink_me(self, tea):
        if tea == self.problem:
            return self.result
        else:
            return "fine"


class Human(Mammal):
    problem = "paint"
    result = die

    def drink_me(self, tea):
        if tea == self.problem:
            return self.result
        else:
            return super().drink_me(tea)

我希望这有帮助。这与您原来的代码有点不同,但老实说,您发布的代码需要一些混乱的super()调用。我认为您的目标是Mammal()的一个子类,它为drinkMe()的结果提供了额外的选项

采用这种方法怎么样:所有的Mammals现在都有了一个包含饮料和结果的字典。子类使用自己对饮料的自定义响应来更新此词典。这样就有了一个函数,它只返回饮料的响应。如果实例喝了没有响应集的东西,应该怎么办?现在只需在drinkMe()中添加一次异常处理。你知道吗

class Mammal:
    def __init__(self):
        self.problems = {'sage': 'sick'}

    def drinkMe(self, tea):
        return self.problems[tea]


class Human(Mammal):
    def __init__(self):
        super().__init__()
        self.problems.update({'paint': 'die'})

jo = Human()
print(jo.drinkMe("sage"))

编辑:更多地评论为什么原始代码打印fine而不是sick。你知道吗

当您建立名为joHuman时,jo.problem被设置为paint。所以,jo.drinkMe调用super.drinkMe,再次检查tea == self.problem。但是请记住,您仍然没有改变jo.problem。它仍然设置为paint,因此fine返回。你知道吗

self是实例本身,在本例中它是jo,当您调用super.drinkMe()时,super.__init__()不会再次运行,因此self.problem仍然设置为原来的值。你知道吗

相关问题 更多 >