Python面向对象编程:金字塔类多继承面积计算错误排查及Square继承关系调整咨询
Python面向对象编程:金字塔类多继承面积计算错误排查及Square继承关系调整咨询
嗨,我来帮你梳理下这个问题的根源,以及如何在让Square继承Rectangle的前提下解决计算错误~
一、原代码输出错误的核心原因
咱们先看你最开始的代码,为什么会输出错误的结果?问题出在属性名冲突上:
Square继承自Rectangle,初始化时会把self.w和self.h都设为传入的length(也就是你创建Pyramid时的base=3);- 但随后在
Pyramid的__init__里,你调用了Triangle.__init__,这个方法会给self.h赋值为height=5——直接把Square继承来的self.h给覆盖了! - 当你调用
Square.perimeter(self)计算底面周长时,用的已经是被覆盖后的self.h=5,而不是原来的3,所以周长变成了(3+5)*2=16,代入面积公式后结果就偏离了预期的39。
二、让Square继承Rectangle的正确实现方案
要保留Square对Rectangle的继承,同时避免属性冲突,有两种简单可行的方法:
方法1:修改Triangle的属性名,避免覆盖
把Triangle里用来存高度的属性名改成和Rectangle不冲突的,比如self.height而不是self.h:
class Rectangle: def __init__(self, width, height): self.w = width self.h = height def area(self): return self.w * self.h def perimeter(self): return (self.w + self.h) * 2 class Square(Rectangle): def __init__(self, length): super().__init__(width=length, height=length) class Triangle: # 修改参数和属性名,避开self.h def __init__(self, base, height): self.base = base self.height = height def area(self): return 0.5 * self.base * self.height class Pyramid(Square, Triangle): def __init__(self, base, height): Square.__init__(self, length=base) Triangle.__init__(self, base=base, height=height) def area(self): base_area = Square.area(self) # 这里用Triangle的self.height,不会影响Square的self.h lateral_area = 0.5 * Square.perimeter(self) * self.height return base_area + lateral_area pyramid = Pyramid(3, 5) print(pyramid.area()) # 输出39,符合预期
方法2:给Pyramid单独存储高度属性
如果不想修改Triangle的代码,可以在Pyramid里把金字塔的高度存为独立属性,不使用self.h:
class Rectangle: def __init__(self, width, height): self.w = width self.h = height def area(self): return self.w * self.h def perimeter(self): return (self.w + self.h) * 2 class Square(Rectangle): def __init__(self, length): super().__init__(width=length, height=length) class Triangle: def __init__(self, l, h): self.l = l self.h = h def area(self): return 0.5 * self.l * self.h class Pyramid(Square, Triangle): def __init__(self, base, height): Square.__init__(self, length=base) # 把金字塔高度存为单独属性,避免和Square的self.h冲突 self.pyramid_height = height # 如果不需要Triangle的area方法,甚至可以不调用它的__init__ def area(self): return Square.area(self) + 0.5 * Square.perimeter(self) * self.pyramid_height pyramid = Pyramid(3, 5) print(pyramid.area()) # 输出39,符合预期
这两种方法都能解决属性覆盖的问题,同时保留Square继承Rectangle的设计,让代码逻辑更清晰~
备注:内容来源于stack exchange,提问作者Matin_Kh
相关产品推荐
相关产品推荐

