3

我有一个教师的任务,试图用 Python 教授 OOP。我非常熟悉 C++ 和 C# 中的 OOP,但很难弄清楚我的一些代码中发生了什么。它可以工作,并且两个类都可以按我的意愿运行,但是我必须添加一些奇怪的代码才能使其工作,但我不明白为什么。

具体引用从第 64 行开始的代码

class Cone(Cylinder):

    #Constructor
    def __init__ (self, radius, height):        
        Cylinder.__init__(self, radius, height)
        self.calcVolume()


    def calcVolume(self):
        Cylinder.calcVolume(self)
        self.__volume = Cylinder.GetVolume(self) * (1.0/3.0)

所以在实现时Cone我不明白为什么Cylinder.calcVolume()当锥体的构造函数调用圆柱体的构造函数时没有调用。如果代码被隐式调用但我被迫显式调用该方法,那么代码对我来说会更有意义。一些指导或解释会很棒。

发布后我进行了此更改是否更有意义?

class Cone(Cylinder):

    #Constructor
    def __init__ (self, radius, height):        
        Cylinder.__init__(self, radius, height)
        self.calcVolume()


    def calcVolume(self):
        self.__volume = self.GetBase().GetArea() * self.GetHeight() * (1.0/3.0)
4

2 回答 2

3

规则非常简单:当方法被调用时,它的名字是根据方法解析顺序来解析的(这很棘手,因为 Python 有多重继承)。

解析名称后,Python 停止搜索(我正在简化)。调用父类的方法(或任何其他方法)取决于具体方法。隐式执行它可能是问题的常见原因(例如,当您想要覆盖父类中的某些方法时)。

此外,要调用父方法,请使用super(). 而不是在Cone课堂上写这个:

Cylinder.__init__(self, radius, height)

写这个:

super(Cone, self).__init__(self, radius, height)

这使它更加灵活:它只是将寻找合适的方法委托给 MRO,然后 MRO 按特定顺序检查父类(在这种情况下,它确实会找到Cylinder.__init__)。

更多阅读:

于 2013-07-17T03:23:29.523 回答
3

这就是您调用时会发生的情况Cone.__init__()

  • 它执行Cylinder.__init__()
  • 它依次调用self.calcVolume()
  • 因为继承,解析顺序在Cone类型上找到方法,
  • 它调用Cone.calcVolume()而不是Cylinder.calcVolume().

__init__()我想你想打电话:

  • Cone.calcVolume(self)Cone.__init__(), 或
  • Cylinder.calcVolume(self)Cylinder.__init__().

当然,如果您使用的是新样式类(继承自object),那么您可以使用type(self).calcVolume(self); 但是type(self),在旧式课程上,将为您提供instance类型而不是实际课程,这在您的情况下不起作用。


完整示例:

class Circle():
    #Constructor
    def __init__ (self, radius):
        self.__radius = radius
        self.calcArea()
    def calcArea(self, PI = 3.14):
        self.__area = (self.__radius**2) * PI
    #Get Functions
    def GetArea(self):
        return self.__area
    def GetRadius(self):
        return self.__radius
    #Set Functions
    def SetRadius(self, radius):
        self.__radius = radius
        self.calcArea()

class Cylinder():
    #Constructor
    def __init__(self, radius, height):
        self.__height = height
        self.__base = Circle(radius)
        Cylinder.calcVolume(self)
    def calcVolume(self):
        self.__volume = self.__base.GetArea() * self.__height
    #Get Functions
    def GetVolume(self):
        return self.__volume
    def GetBase(self):
        return self.__base
    def GetRadius(self):
        return self.__base.GetRadius()
    def GetHeight(self):
        return self.__height
    #Set Functions
    def SetRadius(self, radius):
        self.__base.SetRadius(radius)
        self.calcVolume()
    def SetHeight(self, height):
        self.__height = height
        self.calcVolume()


class Cone(Cylinder):
    #Constructor
    def __init__ (self, radius, height):
        Cylinder.__init__(self, radius, height)
        Cone.calcVolume(self)
    def calcVolume(self):
        Cylinder.calcVolume(self)
        self.__volume = Cylinder.GetVolume(self) * (1.0/3.0)
    #Get Functions
    def GetVolume(self):
        return self.__volume
    #Set Functions
    def SetRadius(self, radius):
        Cylinder.SetRadius(self, radius)
        self.calcVolume()
    def SetHeight(self, height):
        Cylinder.SetHeight(self, height)
        self.calcVolume()


def main():
        cylinder = Cylinder(5, 6)
        cone = Cone(5, 6)
        circle = Circle(5)
        print cylinder.GetVolume()
        print cone.GetVolume()
        print circle.GetArea()
        cone.SetHeight(7)
        print cone.GetVolume()

main()
于 2013-07-17T04:09:14.740 回答