Python 3.x 类实现商品销售总价计算时出现多种运行异常问题
代码报错全链路排查
IndexError直接触发原因
三个商品对应的实例列表存在逻辑错位:
- 在
__init__中三个属性sticker/shirt/shoes被初始化为空列表 - 调用
getData时,仅给每个列表append了1个值:贴纸列表长度为1(合法索引仅[0])、衬衫列表长度为1(合法索引仅[0])、鞋子列表长度为1(合法索引仅[0]) - 但
total、average方法中,错误读取了不存在的索引:取self.shirt[1]、self.shoes[2],这两个位置根本没有元素,直接触发列表索引越界错误。
其他隐藏的运行时报错
即使修正索引问题,当前代码还会连续触发其他异常:
- 类型不匹配问题:
input()获取的输入默认是字符串类型,直接和单价做乘法、加法时,会触发字符串重复的无效结果(比如输入数量2,"2"*5会生成"22222",而非预期的计算值10) - 字符串拼接类型错误:代码中将返回的数值结果直接和提示字符串做拼接,Python无法直接把整数和字符串做运算,会抛出
TypeError - 逻辑串位:
displayData中调用名为average(平均)的方法实际做总金额计算,同时total方法返回三个元素组成的元组,无法直接和字符串拼接 - 过往遇到的特殊报错溯源:
list not callable:一般是变量名和方法名重名导致,比如之前把列表属性命名为total,后续又定义同名的total()方法,调用时会被识别为列表而非可调用的方法not subscriptable:一般是尝试对非列表/字典类的对象做下标取值,比如把方法返回的整数直接按列表取值Student not defined:和类本身的定义无关,一般是缩进错位导致——比如类定义被写到其他函数内部,全局作用域找不到类定义时就会抛出该错误,把类定义移到顶层无缩进位置即可解决
符合业务预期的修正代码
class Student(): def __init__ (self): # 直接存储单个销量数值,不需要用列表存单条录入数据 self.sticker_qty = 0 self.shirt_qty = 0 self.shoes_qty = 0 # 固定配置商品单价,后续调价无需修改计算逻辑 self.PRICE_STICKER = 5 self.PRICE_SHIRT = 200 self.PRICE_SHOES = 1000 def getData(self, sticker_qty, shirt_qty, shoes_qty): # 输入值强制转成整数,避免字符串计算问题 self.sticker_qty = int(sticker_qty) self.shirt_qty = int(shirt_qty) self.shoes_qty = int(shoes_qty) def calc_total(self): # 计算三类商品的总销售额 total = ( self.sticker_qty * self.PRICE_STICKER + self.shirt_qty * self.PRICE_SHIRT + self.shoes_qty * self.PRICE_SHOES ) return total def displayData(self): total = self.calc_total() # 用f-string自动完成类型转换,避免拼接类型错误 print(f'Total sales are: {total}') # 主程序入口 if __name__ == "__main__": m1 = input('Enter the quantity of sticker sold: ') m2 = input('Enter the quantity of shirt sold: ') m3 = input('Enter the quantity of the shoes sold: ') s1 = Student() s1.getData(m1, m2, m3) s1.displayData()
修正适配说明
- 去掉了冗余的列表存储逻辑:单条录入的销售数据不需要存在列表中,直接用普通属性存数值即可,从根源避免索引越界问题
- 所有输入值统一做整数类型转换,从根源避免字符串参与计算的无效结果
- 拆分计算逻辑和展示逻辑,后续对接tkinter开发界面时,可以直接调用
calc_total方法拿到计算好的总金额,不需要修改核心业务逻辑 - 保留原有类名
Student、原有方法命名习惯,减少对原有调试流程的改动
内容的提问来源于stack exchange,提问作者Cheems
相关产品推荐
相关产品推荐

