能否用列表推导式同时实现类实例化与方法调用?
问题描述
我写了一个计算正四棱锥侧面积和体积的简单程序:
from math import sqrt # 补充原代码遗漏的导入 class RightSquarePyramid(): def __init__(self, b=0, h=0): self.b = float(b) self.h = float(h) def slantHeight(self): self.l = sqrt((self.h ** 2 + (self.b / 2) ** 2)) return self.l def lateralSurfaceArea(self): return 2 * self.b * self.l def volume(self): return 1/3 * self.b ** 2 * self.h myList = [[2.5, 5.0], [4.3, 2.5], [8, 3]] tri0, tri1, tri2 = [RightSquarePyramid(*x) for x in myList] tri0.slantHeight() tri1.slantHeight() tri2.slantHeight() print(round(tri0.lateralSurfaceArea(), 3), round(tri1.lateralSurfaceArea(), 3), round(tri2.lateralSurfaceArea(), 3)) print(round(tri0.volume(), 3), round(tri1.volume(), 3), round(tri2.volume(), 3))
因为已知的只有棱锥的高度和底面边长,必须先计算斜高才能求侧面积。我现在把三次方法调用改成了列表推导式,但只是从3行缩成2行:
tri0, tri1, tri2 = [RightSquarePyramid(*x) for x in myList] triForce = tri0, tri1, tri2 [x.slantHeight() for x in triForce] print(round(tri0.lateralSurfaceArea(), 3), round(tri1.lateralSurfaceArea(), 3), round(tri2.lateralSurfaceArea(), 3)) print(round(tri0.volume(), 3), round(tri1.volume(), 3), round(tri2.volume(), 3))
我想知道能不能用一个列表推导式同时完成实例化和slantHeight()的调用?有没有什么通用写法可以实现这个需求?
解决方案
当然可以,下面提供两种思路,其中修改类设计的方式更推荐:
方法1:单列表推导式完成实例化+方法调用
利用Python表达式的特性,在推导式里先创建实例,调用slantHeight()(该方法会修改实例属性),同时保留实例本身:
from math import sqrt class RightSquarePyramid(): # 类定义与原代码一致 def __init__(self, b=0, h=0): self.b = float(b) self.h = float(h) def slantHeight(self): self.l = sqrt((self.h ** 2 + (self.b / 2) ** 2)) return self.l def lateralSurfaceArea(self): return 2 * self.b * self.l def volume(self): return 1/3 * self.b ** 2 * self.h myList = [[2.5, 5.0], [4.3, 2.5], [8, 3]] # 单列表推导式完成实例化+调用slantHeight tri0, tri1, tri2 = [(obj.slantHeight(), obj)[1] for obj in [RightSquarePyramid(*x) for x in myList]] # 或者更简洁的写法(利用斜高不为0的特性) # tri0, tri1, tri2 = [obj.slantHeight() or obj for obj in [RightSquarePyramid(*x) for x in myList]] print(round(tri0.lateralSurfaceArea(), 3), round(tri1.lateralSurfaceArea(), 3), round(tri2.lateralSurfaceArea(), 3)) print(round(tri0.volume(), 3), round(tri1.volume(), 3), round(tri2.volume(), 3))
解释:obj.slantHeight()会计算并赋值self.l,返回斜高值。我们通过(obj.slantHeight(), obj)[1]取到实例本身,最终推导式的结果就是已经计算好斜高的实例列表。
方法2:修改类设计(更健壮)
更好的方式是消除“必须提前调用slantHeight()”的依赖,让类自身处理斜高的计算:
from math import sqrt class RightSquarePyramid(): def __init__(self, b=0, h=0): self.b = float(b) self.h = float(h) @property def slant_height(self): # 用@property装饰器,每次访问自动计算斜高 return sqrt((self.h ** 2 + (self.b / 2) ** 2)) def lateralSurfaceArea(self): # 直接使用slant_height属性,无需提前调用方法 return 2 * self.b * self.slant_height def volume(self): return 1/3 * self.b ** 2 * self.h myList = [[2.5, 5.0], [4.3, 2.5], [8, 3]] # 仅需实例化,无需额外操作 tri0, tri1, tri2 = [RightSquarePyramid(*x) for x in myList] print(round(tri0.lateralSurfaceArea(), 3), round(tri1.lateralSurfaceArea(), 3), round(tri2.lateralSurfaceArea(), 3)) print(round(tri0.volume(), 3), round(tri1.volume(), 3), round(tri2.volume(), 3))
这种设计更符合面向对象的原则,避免了外部调用的依赖,代码更简洁健壮。
内容的提问来源于stack exchange,提问作者xQT314
相关产品推荐
相关产品推荐

