三级菜单

这是老师写的代码,自己进行分析:

menu的内容:

menu = {
    '北京': {
        '海淀': {
            '五道口': {
                'soho': {},
                '网易': {},
                'google': {}
            },
            '中关村': {
                '爱奇艺': {},
                '汽车之家': {},
                'youku': {},
            },
            '上地': {
                '百度': {},
            },
        },
        '昌平': {
            '沙河': {
                '老男孩': {},
                '北航': {},
            },
            '天通苑': {},
            '回龙观': {},
        },
        '朝阳': {},
        '东城': {},
    },
    '上海': {
        '闵行': {
            "人民广场": {
                '炸鸡店': {}
            }
        },
        '闸北': {
            '火车战': {
                '携程': {}
            }
        },
        '浦东': {},
    },
    '山东': {},
}

写一个三级菜单的代码

def threeML(dic):
    while 1:
        for k in dic:print(k)
        key=input('请输入地名:').strip()
        if key=='b' or key=='q':return key
        elif key in dic.keys()and dic[key]:#表示输入的这个key在menu中,且这个key的字典不为空
            ret=threeML(dic[key])#发生了一次调用
            if ret=='q':return 'q'
        elif (not dic.get(key)) or (not dic[key]):
            continue
threeML(menu)

对这段代码进行分析

第一次调用

#第一次调用
def threeML(dic):
    while 1:
        for k in dic:print(k)#这里的执行结果是北京、上海、山东
        key=input('请输入地名:').strip()#北京、上海、山东任意输入一个地名,本范例输入北京
        if key=='b' or key=='q':return key#如果输入的是b或者q,则返回b或者q,代码结束
        elif key in dic.keys()and dic[key]:#表示输入的这个key在menu中,且这个key的字典不为空,北京下面还有子菜单所以不为空,继续执行
            ret=threeML(dic[key])#利用递归,发生了第一次调用,
            if ret=='q':return 'q'
        elif (not dic.get(key)) or (not dic[key]):
            continue
threeML(menu)

第二次调用

此时key等于北京

则key表示

key={
        '海淀': {
            '五道口': {
                'soho': {},
                '网易': {},
                'google': {}
            },
            '中关村': {
                '爱奇艺': {},
                '汽车之家': {},
                'youku': {},
            },
            '上地': {
                '百度': {},
            },
        },
        '昌平': {
            '沙河': {
                '老男孩': {},
                '北航': {},
            },
            '天通苑': {},
            '回龙观': {},
        },
        '朝阳': {},
        '东城': {},
    }

代码

#第二次调用
def threeML(dic):
    while 1:
        for k in dic:print(k)#这里的执行结果是海淀、昌平、朝阳、东城
        key=input('请输入地名:').strip()#海淀、昌平、朝阳、东城任意输入一个地名,本范例输入昌平
        if key=='b' or key=='q':return key#如果输入的是b或者q,则返回b或者q,代码结束
        elif key in dic.keys()and dic[key]:#表示输入的这个key在menu中,且这个key的字典不为空,昌平下面还有子菜单所以不为空,继续执行
            ret=threeML(dic[key])#利用递归,发生了调用,
            if ret=='q':return 'q'
        elif (not dic.get(key)) or (not dic[key]):
            continue
threeML(menu)

第三次调用

此时key等于昌平

key={
    '沙河': {
                '老男孩': {},
                '北航': {},
            },
    '天通苑': {},
    '回龙观': {},
    }
#第三次调用
def threeML(dic):
    while 1:
        for k in dic:print(k)#这里的执行结果是沙河、天通苑、回龙观
        key=input('请输入地名:').strip()#沙河、天通苑、回龙观任意输入一个地名,本范例输入回龙观
        if key=='b' or key=='q':return key#如果输入的是b或者q,则返回b或者q,代码结束
        elif key in dic.keys()and dic[key]:#由于此时回龙观的下级菜单为空,所以不能执行这段代码
            ret=threeML(dic[key])
            if ret=='q':return 'q'
        elif (not dic.get(key)) or (not dic[key]):#此时执行这段代码,由于此时无论是dic.get(key)还是dic[key]的结果都为空,所以其布尔值都为False,not dic.get(key)和not dic[key]就是True,然后执行下一段代码
            continue#当上一条利用not将false变为true后,开始执行continue,然后continue跳出当前循环,开始新一轮的while循环
threeML(menu)

此时代码运行过程如下:

def threeML(dic):
    while 1:
        for k in dic:print(k)#这里的执行结果仍然是沙河、天通苑、回龙观
        key=input('请输入地名:').strip()#沙河、天通苑、回龙观任意输入一个地名,本范例继续输入回龙观则代码会陷入死循环
        if key=='b' or key=='q':return key#如果输入的是b或者q,则返回b或者q,结束本次代码,同时将b或者q返回给第三次调用(递归函数的原理)
        elif key in dic.keys()and dic[key]:
            ret=threeML(dic[key])
            if ret=='q':return 'q'
        elif (not dic.get(key)) or (not dic[key]):
            continue
threeML(menu)

当将b返回给第三次调用

def threeML(dic):
    while 1:
        for k in dic:print(k)
        key=input('请输入地名:').strip()
        if key=='b' or key=='q':return key
        elif key in dic.keys()and dic[key]:
            ret=threeML(dic[key])#此时ret=b
            if ret=='q':return 'q'#由于b不等于q,当前的if循环结束,所以又开始了新一轮的while循环,不过此时重新开始海淀、朝阳、东城、昌平的新一轮循环,即返回上一级菜单
        elif (not dic.get(key)) or (not dic[key]):
            continue
threeML(menu)

注意上面的代码不难理解,难点在于b和q,b的作用是返回上一次菜单,q的作用是直接退出

方法二:利用对象进行编程

l=[menu]
while l:
    for key in l[-1]:print(key)#没看明白这里为何是-1
    k=input('请输入:').strip()
    if k in l[-1].keys() and l[-1][k]:l.append(l[-1][k])
    elif k=='b':l.pop()
    elif k=='q':break
    else:continue

参考:https://www.cnblogs.com/Eva-J/articles/7205734.html#_label4

 

posted @ 2019-02-27 00:12  舒畅123  阅读(133)  评论(0)    收藏  举报