python:在继承的类中连续的调用?

2024-10-02 22:25:17 发布

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

我遇到了一个我不理解的问题,它相当复杂,所以我尽力在这里把它分解。请看一下下面的实现。我的问题是:为什么父类调用其子类的\uugetitem\uu方法,而不是调用自己的?在

class Father(object):
    ''' Father class '''
    def __init__(self,name,gender):
        print('call __init__ Father')      
        self._name = name
        # trying to call Father's __getitem__ here
        self._gender=self[gender] 

    def __getitem__(self,key):
        print('call __getitem__  Father')
        return key

class Child(Father):
    ''' inherited from Father class '''
    def __init__(self, name, gender, age=None):
        print('call __init__ Child')
        super(self.__class__, self).__init__(name, gender)
        self._age = age

    def __getitem__(self, key):
        print('call __getitem__  Child')
        if self._name == 'Marie' and self._age == None:
            print('I am not sure, how old I am')
        return  super(self.__class__, self).__getitem__(key)

one=Child('Klaus','male','12')        
other=Child('Marie','female')

将出现的错误消息是:

^{pr2}$

我不会料到会有这种行为。我试图从父亲那里继承Child并添加功能,所以上面所有的语法都是必要的,在我更复杂的代码中也是有意义的。 one=Child('Klaus','male','12')的第一个示例运行得很顺利,我们已经可以看到,在父构造函数中,子元素的\uugetitem_Uu被调用了。 在other=Child('Marie','female')的第二个例子中,我们可以理解为什么这个反向调用会困扰我。在这里,只有在定义self.\u age=age时,代码才会运行。在

从建议这个相反的调用如何有用以及它的目的,我将非常感谢如何显式地调用父中的自己的getitem_Uu方法的解决方案。只是写作

self._gender=self.__getitem__(gender) #instead of
self._gender=self[gender]

不幸的是,它没有做到这一点,并产生同样的错误。在


Tags: keynameselfchildageinitdefcall
2条回答
# trying to call Father's __getitem__ here
self._gender=self[gender]

这里使用的__getitem__方法将通过self的实际类查找。如果selfChild的实例,它将使用Child.__getitem__。您可以将其更改为显式使用Father.__getitem__

^{pr2}$

虽然你的整体设计还是有点混乱,而且可能会导致更多的问题。在


无关但重要:

super(self.__class__, self)

永远不要这样做。如果在任何一个类中这样做的话,它就会中断。必须显式地提供类名。在

要修复此问题,只需交换Child__init__中的初始化顺序,这样Child.__getitem__所需的Child属性在需要之前被初始化:

def __init__(self, name, gender, age=None):
    print('call __init__ Child')
    self._age = age
    super(Child, self).__init__(name, gender)

这个修复对于这个特定的场景是唯一的,但是它通常也是正确的修复;一般来说,父类的唯一责任是不要不必要地中断子类化,但是不能期望它们计划让子类创建新的类不变量,并尝试预先适应它们。子类应该完全了解父类,子类的责任是确保它不会破坏父类的任何行为,在这种情况下,通过确保在父类可能使用需要它们的方法之前定义了所有新的必需属性。在

至于它为什么调用子类的__getitem__,这就是子类化的默认工作方式(不仅在Python中,而且在大多数OO语言中)。Father.__init__Child.__init__接收的self仍然是Child对象,因此查找首先检查Child上的__getitem__。如果不这样做,您将有混乱的行为,其中一些索引在Child上调用__getitem__而有些没有,这将使它非常不直观。在

如果出于某种原因,您绝对必须在Father.__init__中只使用Father__getitem__,那么您只需要明确您调用的是哪个方法。不要使用self[gender]self.__getitem__(gender)(这两种方法都要经过正常的查找过程),do Father.__getitem__(self, gender)显式调用方法的Father版本(还需要显式地传递self,因为您使用的是未绑定方法而不是绑定方法)。在

在初始化过程中,父方法和子方法将不会被完全调用,因此在初始化过程中不会完全调用父方法:

^{pr2}$

相关问题 更多 >