需求:
用户可以从最外层的菜单依次进入内层菜单
用户输入b,可以从当前菜单退回到上一层
用户输入q可以退出整个程序
一、初级版
思路:
为了在用户输入错误的情况下能够重新输入,每一层都需要一个循环。
当用户进入最内层(公司层)的时候,提示用户已经是最后一层了,只能选择回退或者退出。
menu = {
'北京':{
'海淀':{
'五道口':{
'soho':{},
'网易':{},
'google':{}
},
'中关村':{
'爱奇艺':{},
'汽车之家':{},
'youku':{},
},
'上地':{
'百度':{},
},
},
'昌平':{
'沙河':{
'老男孩':{},
'北航':{},
},
'天通苑':{},
'回龙观':{},
},
'朝阳':{},
'东城':{},
},
'上海':{
'闵行':{
"人民广场":{
'炸鸡店':{}
}
},
'闸北':{
'火车站':{
'携程':{}
}
},
'浦东':{},
},
'山东':{},
}
while True:
#打印城市
for i in menu:
print(i)
#请用户输入选择的城市
choice=input('>>>').strip()
#如果城市在字典里
if choice in menu:
while True:
#打印区
for j in menu[choice]:
print(j)
#请用户输入选择的区
choice2=input('>>>').strip()
#如果区在字典里
if choice2 in menu[choice]:
while True:
#打印街道
for k in menu[choice][choice2]:
print(k)
#请用户输入街道
choice3=input('>>>').strip()
#如果街道在字典里
if choice3 in menu[choice][choice2]:
while True:
#打印公司
for v in menu[choice][choice2][choice3]:
print(v)
#公司下面没有内容了,所以请用户做出选择:是退到上一层,还是退出程序?
choice4=input('已经是最后一层。输入b回退,输入q退出程序>>>').strip()
#如果用户输入b,则打破最内层(第四层)的循环,跳到第三层,实现回退
if choice4=='b':
break
#如果用户输入q,则退出整个程序,并告知用户是从第四层退出的
elif choice4=='q':
exit('再见第四层')
#如果用户输入有误,则提示重新输入,回到当前循环的开始
else:
print('输入有误,请重新输入!')
#如果用户在第三层输入q,则退出程序,并提示是在第三层退出的
elif choice3=='q':
exit('再见第三层')
#如果用户输入b,则退出第三层循环,回到第二层循环
elif choice3=='b':
break
#如果用户输入有误,则提示重新输入,并回到当前循环的开始
else:
print('输入有误,请重新输入!')
#如果用户输入q,则退出程序,并提示是在第二层退出的
elif choice2 =='q':
exit('再见第二层')
#如果用户输入b,则退出第二层循环,回到第一层循环
elif choice2=='b':
break
#如果用户输入有误,则提示重新输入,并回到当前循环的开始
else:
print('输入有误,请重新输入!')
#如果用户输入q,则退出程序,并提示是从第一层退出的
elif choice=='q':
exit('再见第一层')
#如果用户输入b,由于当前已经是最外层,无路可退,也不希望因此结束程序
# (程序员很倔强,只有输入q才可以退出)
#所以这里用了一个continue,回到当前循环的最外层,让用户重新输入
elif choice=='b':
continue
#如果输入有误,则提示重新输入,并回到循环的开始
else:
print('输入有误,请重新输入!')
二、优化版
思路:
初级版的代码存在大量重复。我们的优化版代码则通过不断更新menu(更新当前位置)并把访问过的菜单存储到record列表中(记录来时的路),来实现代码的简化。
menu = {
'北京':{
'海淀':{
'五道口':{
'soho':{},
'网易':{},
'google':{}
},
'中关村':{
'爱奇艺':{},
'汽车之家':{},
'youku':{},
},
'上地':{
'百度':{},
},
},
'昌平':{
'沙河':{
'老男孩':{},
'北航':{},
},
'天通苑':{},
'回龙观':{},
},
'朝阳':{},
'东城':{},
},
'上海':{
'闵行':{
"人民广场":{
'炸鸡店':{}
}
},
'闸北':{
'火车站':{
'携程':{}
}
},
'浦东':{},
},
'山东':{},
}
#这个空列表用来记录我们访问过的菜单
record=[]
while True:
#打印当前菜单中所有的键。第一次循环就是打印北京,上海,山东。
for i in menu:
print(i)
#请用户输入。第一次用户可以选择输入一个城市。
choice=input('>>>').strip()
#如果用户输入的内容是菜单的键
if choice in menu:
#将当前菜单存储在record中。
# 第一次执行这个操作,存入的就是{北京:……,上海:……,山东:……}
record.append(menu)
#将菜单更新为下一层。
# 例如,刚才输入了北京,那么就把菜单更新为{海淀:……,昌平:……,朝阳:……,东城:……}
menu=menu[choice]
#如果用户输入了b
elif choice=='b':
#判断record是否为空,为空就什么也不做,回到循环的开头
if record:
#不为空则把record中的最后一项取出来,赋值给menu。
#最后一项就是我们刚走过的路,这样就能实现回退。
menu=record.pop()
#如果用户输入了q
elif choice=='q':
#退出程序
exit('再见!')
#如果用户输入的既不是字典的键,也不是b/q,则提示输入有误,回到循环的开头。
else:
print('输入有误,请重新输入!')
为了帮助大家理清升级版的运作过程,我们再来仔细看一下代码结构。
其实每次循环,程序都做了三大工作:
- 打印菜单
- 请用户输入
- 判断,并根据判断做点什么
接下来我就把几次循环的具体工作流程用文字写下来:
/*第一次循环*/
打印:北京 上海 山东(每次打印的都是menu里的键)
输入:北京
判断:符合 choice in menu
把原来的menu {北京:……,上海:……,山东:……}存进record
把menu更新为{海淀:……,昌平:……,朝阳:……,东城:……}
/*第二次循环*/
打印:海淀 昌平 朝阳 东城
输入:海淀
判断:符合choice in menu
把原来的menu {海淀:……,昌平:……,朝阳:……,东城:……}存进record
把menu更新为{五道口:……,中关村:……,上地:……}
/*第三次循环*/
打印:五道口 中关村 上地
输入:b
判断:符合 choice==’b’
把record中的最后一项,也就是{海淀:……,昌平:……,朝阳:……,东城:……}取出来,并把它赋给menu
/*第四次循环*/
打印:海淀 昌平 朝阳 东城
输入:b
判断:符合 choice==’b’
把record中的最后一项,也就是{北京:……,上海:……,山东:……}取出来
并把它赋给menu
/*第五次循环*/
打印:北京 上海 山东
输入:上海
判断:符合choice in menu
把原来的menu {北京:……,上海:……,山东:……}存进record
把menu更新为 {闵行:……,闸北:……,浦东:……}
/*第六次循环*/
打印:闵行 闸北 浦东
输入:q
判断:符合 choice==’q’
退出程序,再见!