介绍
计划和媳妇去云南旅游,媳妇让做一下预算,正好当时正在写python代码,就随手一个print(sum([...]))计算了出来,后来媳妇说分分类,有些是确定的,有些无法确定,就又加了些逻辑进去,媳妇称赞的同时又灵魂一击:一个计算器不就解决了吗?哈哈哈,最后本着“杀鸡用牛刀”的目的,又花了些时间完善了一下代码逻辑和注释。
该小段代码主要用了字典dict、求和sum()以及逻辑判断,既然写了就发出来,说不定可以帮助到某位同学呢(大牛大神们请绕开,不敢班门弄斧U_U),另外需要说明的是,该代码中的字典只是为了应用,所以不包含字典的所有用法。
源码
# 根据费项计算总费用
def sumFees(fees):
'''
参数说明:
1、fees为一个两层级的字典,外层字典的value必须为字典格式,否则会被忽略
2、内层的字典的value必须为数字,否则可能会强制转为0
3、内层的字典的value如果为负数,也会正常进行运算
示例格式:
fees = {
'机票': {'北京 >>> 昆明': 803*2, '丽江 >>> 郑州': 900*2},
'住宿': {'大理古城': 300, '大理市区': 200, '丽江': 588, 'y郑州': 150*4},
'租车': {'大理': 135},
'铁路': {'昆明 >>> 大理': 145*2, '大理 >>> 丽江': 49*2, '郑州 >>> 北京': 309*2},
'门票': {'苍山景区': 290*2, '环洱海景点': 200*2, 'y丽江千古情': 230*2, 'y玉龙雪山': 438},
'餐食': {'大理': 1000, 'y丽江': 1087, 'y郑州':879},
'购物': {'大理': 2000, 'y丽江': 1500},
'其他': {'y公共交通': 40*2+20*2+6*2+20*2, '租车油费':76, '保险':20*2+12*2}
}
'''
# 如果传参不是字典类型,直接处理
if not isinstance(fees, dict):
print('传参不是字典类型,请重新设置!')
return ''
# 定义空字典,供后面使用
noConfirm = {} # 预估费用明细
confirmed = {} # 确定费用明细
totalFees = {} # 总费用明细
totalFeesConfirmed = {} # 确定总费用明细
totalFeesNoConfirm = {} # 预估总费用明细
# 第一个for循环:处理外层字典
for item in fees:
itemValueTem = fees[item]
temDict1 = {}
temDict2 = {}
#判断外层字典的value是否为字典
if isinstance(itemValueTem, dict):
# 第二个for循环:处理内层字典
for item2 in itemValueTem:
itemValue = itemValueTem[item2]
# 判断内层字典的value是否为数值,如果不是数值,则强制转换为浮点数,转换失败则强制赋值为0
if not isinstance(itemValue, (int, float)):
try:
itemValue = float(itemValue)
except:
itemValue = 0
# 如果内层字典的key的第一个字符为“y”,则记为预估费用项,否则记为确定费用项
if item2[0:1].lower() == 'y':
temDict1[item2] = itemValue
else:
temDict2[item2] = itemValue
# 只有临时预估费用和临时确定费用不为空的时候才进入到noConfirm和confirmed
if temDict1:
noConfirm[item] = temDict1
if temDict2:
confirmed[item] = temDict2
else:
print('%s 的参数设置错误,必须为dict类型!' % (item,))
# 确定费用项不为空时,处理确定费用项
if confirmed:
for item3 in confirmed:
# 获取各确定费用项的value,返回一个列表
feeTem3 = confirmed[item3].values()
# 如果列表feeTem3不为空则计算确定总费用,并进入到totalFees和totalFeesConfirmed中
if feeTem3:
item3Sum = sum(feeTem3)
totalFees[item3] = item3Sum
totalFeesConfirmed[item3] = item3Sum
# print('%s 的确定总费用为 %s 元' %(item3, str(item3Sum)))
# 预估费用项不为空时,处理预估费用项
if noConfirm:
for item4 in noConfirm:
# 获取各预估费用项的value,返回一个列表
feeTem4 = noConfirm[item4].values()
# 如果列表feeTem4不为空则计算预估总费用,并进入到totalFees和totalFeesNoConfirm中
if feeTem4:
item4Sum = sum(feeTem4)
# print('%s 的预估总费用为 %s 元' %(item4, str(item4Sum)))
totalFeesNoConfirm[item4] = item4Sum
if item4 not in totalFees:
totalFees[item4] = item4Sum
# 如果预估费用项在总费用中已存在(内层字典中有确定费用也有预估费用),则和已存在的数据相加求和后再赋值
else:
totalFees[item4] = item4Sum + totalFees[item4]
# 如果总费用明细totalFees不为空,进行计算并打印
if totalFees:
totalFee = sum(totalFees.values())
totalFeeConfirmed = sum(totalFeesConfirmed.values())
totalFeeNoConfirm = sum(totalFeesNoConfirm.values())
# 全部都是确定费用项的处理方式
if not noConfirm:
print('总费用(确定):', totalFee)
print('总费用明细(确定):', totalFees)
print('费用明细(确定):', confirmed)
print('没有预估费用')
# 全部都是预估费用项的处理方式
elif not confirmed:
print('总费用(预估):', totalFee)
print('总费用明细(预估):', totalFees)
print('费用明细(预估):', noConfirm)
print('没有确定费用')
# 同时有确定费用项和预估费用项的处理方式
else:
print('总费用:%s(确定:%s,预估:%s)' % (str(totalFee), str(totalFeeConfirmed), str(totalFeeNoConfirm)))
print('总费用明细(确定):', totalFeesConfirmed)
print('总费用明细(预估):', totalFeesNoConfirm)
print('费用明细(确定):', confirmed)
print('费用明细(预估):', noConfirm)
else:
print('没有设置数据!')
# 为了保证函数的完整性,添加一个空返回值
return ''
函数调用及执行结果(以下都是测试数据,不是我俩旅行的实际费用)
调用1:确定费用项和预估费用项都有
if __name__ == '__main__':
travelFees = {
'机票': {'北京 >>> 昆明': 803*2, '丽江 >>> 郑州': 900*2},
'住宿': {'大理古城': 300, '大理市区': 200, '丽江': 588, 'y郑州': 150*4},
'租车': {'大理': 135},
'铁路': {'昆明 >>> 大理': 145*2, '大理 >>> 丽江': 49*2, '郑州 >>> 北京': 309*2},
'门票': {'苍山景区': 290*2, '环洱海景点': 200*2, 'y丽江千古情': 230*2, 'y玉龙雪山': 438},
'餐食': {'大理': 1000, 'y丽江': 1087, 'y郑州':879},
'购物': {'大理': 2000, 'y丽江': 1500},
'其他': {'y公共交通': 40*2+20*2+6*2+20*2, '租车油费':76, '保险':20*2+12*2}
}
sumFees(travelFees)
执行结果
总费用:14891(确定:9755,预估:5136)
总费用明细(确定): {'机票': 3406, '住宿': 1088, '租车': 135, '铁路': 1006, '门票': 980, '餐食': 1000, '购物': 2000, '其他': 140}
总费用明细(预估): {'住宿': 600, '门票': 898, '餐食': 1966, '购物': 1500, '其他': 172}
费用明细(确定): {'机票': {'北京 >>> 昆明': 1606, '丽江 >>> 郑州': 1800}, '住宿': {'大理古城': 300, '大理市区': 200, '丽江': 588}, '租车': {'大理': 135}, '铁路': {'昆明 >>> 大理': 290, '大理 >>> 丽江': 98, '郑州 >>> 北京': 618}, '门票': {'苍山景区': 580, '环洱海景点': 400}, '餐食': {'大理': 1000}, '购物': {'大理': 2000}, '其他': {'租车油费': 76, '保险': 64}}
费用明细(预估): {'住宿': {'y郑州': 600}, '门票': {'y丽江千古情': 460, 'y玉龙雪山': 438}, '餐食': {'y丽江': 1087, 'y郑州': 879}, '购物': {'y丽江': 1500}, '其他': {'y公共交通': 172}}
调用2:只有确定费用项
if __name__ == '__main__':
travelFees = {
'机票': {'北京 >>> 昆明': 803*2, '丽江 >>> 郑州': 900*2},
# '住宿': {'大理古城': 300, '大理市区': 200, '丽江': 588, 'y郑州': 150*4},
'租车': {'大理': 135},
'铁路': {'昆明 >>> 大理': 145*2, '大理 >>> 丽江': 49*2, '郑州 >>> 北京': 309*2},
# '门票': {'苍山景区': 290*2, '环洱海景点': 200*2, 'y丽江千古情': 230*2, 'y玉龙雪山': 438},
# '餐食': {'大理': 1000, 'y丽江': 1087, 'y郑州':879},
# '购物': {'大理': 2000, 'y丽江': 1500},
# '其他': {'y公共交通': 40*2+20*2+6*2+20*2, '租车油费':76, '保险':20*2+12*2}
}
sumFees(travelFees)
执行结果
总费用(确定): 4547
总费用明细(确定): {'机票': 3406, '租车': 135, '铁路': 1006}
费用明细(确定): {'机票': {'北京 >>> 昆明': 1606, '丽江 >>> 郑州': 1800}, '租车': {'大理': 135}, '铁路': {'昆明 >>> 大理': 290, '大理 >>> 丽江': 98, '郑州 >>> 北京': 618}}
没有预估费用
调用3:只有预估费用项
if __name__ == '__main__':
travelFees = {
# '机票': {'北京 >>> 昆明': 803*2, '丽江 >>> 郑州': 900*2},
# '住宿': {'大理古城': 300, '大理市区': 200, '丽江': 588, 'y郑州': 150*4},
'租车': {'y大理': 135},
# '铁路': {'昆明 >>> 大理': 145*2, '大理 >>> 丽江': 49*2, '郑州 >>> 北京': 309*2},
'门票': {'y苍山景区': 290*2, 'y环洱海景点': 200*2, 'y丽江千古情': 230*2, 'y玉龙雪山': 438},
'餐食': {'y大理': 1000, 'y丽江': 1087, 'y郑州':879},
# '购物': {'大理': 2000, 'y丽江': 1500},
'其他': {'y公共交通': 40*2+20*2+6*2+20*2, 'y租车油费':76, 'y保险':20*2+12*2}
}
sumFees(travelFees)
执行结果
总费用(预估): 5291
总费用明细(预估): {'租车': 135, '门票': 1878, '餐食': 2966, '其他': 312}
费用明细(预估): {'租车': {'y大理': 135}, '门票': {'y苍山景区': 580, 'y环洱海景点': 400, 'y丽江千古情': 460, 'y玉龙雪山': 438}, '餐食': {'y大理': 1000, 'y丽江': 1087, 'y郑州': 879}, '其他': {'y公共交通': 172, 'y租车油费': 76, 'y保险': 64}}
没有确定费用
调用4:内层字典的value有非数字类型
if __name__ == '__main__':
travelFees = {
'机票': {'北京 >>> 昆明': 803*2, '丽江 >>> 郑州': 900*2},
'住宿': {'大理古城': 300, '大理市区': 'hello', '丽江': '588', 'y郑州': 150*4},
'租车': {'y大理': 'test135'},
# '铁路': {'昆明 >>> 大理': 145*2, '大理 >>> 丽江': 49*2, '郑州 >>> 北京': 309*2},
# '门票': {'y苍山景区': 290*2, 'y环洱海景点': 200*2, 'y丽江千古情': 230*2, 'y玉龙雪山': 438},
# '餐食': {'y大理': 1000, 'y丽江': 1087, 'y郑州':879},
'购物': {'大理': 2000, 'y丽江': '1500'},
# '其他': {'y公共交通': 40*2+20*2+6*2+20*2, 'y租车油费':76, 'y保险':20*2+12*2}
}
sumFees(travelFees)
执行结果
总费用:8394.0(确定:6294.0,预估:2100.0)
总费用明细(确定): {'机票': 3406, '住宿': 888.0, '购物': 2000}
总费用明细(预估): {'住宿': 600, '租车': 0, '购物': 1500.0}
费用明细(确定): {'机票': {'北京 >>> 昆明': 1606, '丽江 >>> 郑州': 1800}, '住宿': {'大理古城': 300, '大理市区': 0, '丽江': 588.0}, '购物': {'大理': 2000}}
费用明细(预估): {'住宿': {'y郑州': 600}, '租车': {'y大理': 0}, '购物': {'y丽江': 1500.0}}
调用5:内层字典没有数据
if __name__ == '__main__':
travelFees = {
# '机票': {'北京 >>> 昆明': 803*2, '丽江 >>> 郑州': 900*2},
# '住宿': {'大理古城': 300, '大理市区': 200, '丽江': 588, 'y郑州': 150*4},
# '租车': {'y大理': 135},
# '铁路': {'昆明 >>> 大理': 145*2, '大理 >>> 丽江': 49*2, '郑州 >>> 北京': 309*2},
# '门票': {'y苍山景区': 290*2, 'y环洱海景点': 200*2, 'y丽江千古情': 230*2, 'y玉龙雪山': 438},
# '餐食': {'y大理': 1000, 'y丽江': 1087, 'y郑州':879},
# '购物': {'大理': 2000, 'y丽江': 1500},
# '其他': {'y公共交通': 40*2+20*2+6*2+20*2, 'y租车油费':76, 'y保险':20*2+12*2}
}
sumFees(travelFees)
执行结果
没有设置数据!
调用6:内层字典有数据,但是数据为空和非字典数据
if __name__ == '__main__':
travelFees = {
# '机票': {'北京 >>> 昆明': 803*2, '丽江 >>> 郑州': 900*2},
'住宿': {},
'租车': "{'y大理': 135}",
# '铁路': {'昆明 >>> 大理': 145*2, '大理 >>> 丽江': 49*2, '郑州 >>> 北京': 309*2},
# '门票': {'y苍山景区': 290*2, 'y环洱海景点': 200*2, 'y丽江千古情': 230*2, 'y玉龙雪山': 438},
# '餐食': {'y大理': 1000, 'y丽江': 1087, 'y郑州':879},
# '购物': {'大理': 2000, 'y丽江': 1500},
# '其他': {'y公共交通': 40*2+20*2+6*2+20*2, 'y租车油费':76, 'y保险':20*2+12*2}
}
sumFees(travelFees)
执行结果
租车 的参数设置错误,必须为dict类型!
没有设置数据!
调用7:传参不是字典
if __name__ == '__main__':
travelFees = 'testd'
sumFees(travelFees)
执行结果
传参不是字典类型,请重新设置!
网友评论