优秀作业:登录锁定和三层菜单程序展示之二
来自python12期的王同佩的优秀作业:
一、登录验证之readme说明:
整体思路:
1、外层定义一个while True死循环,用于用户输入用户名(用户名输入不对的话,会一直要求输入)
2、初始工作
1、定义2个空的列表,空列表1计划把文件中的2行字符串,分别作为列表存到这里列表变量中,
遍历这个列表后,用于通过索引号取出用户名和密码字段,用于和用户输入的用户名和密码对比进行判断
空列表2计划将修改登录次数后的2个字符串作为元素,写入到这个列表变量中,最终用于写到文件中
2、定义一个flag,当用户输入的用户名==列表中的索引号是0的用户名的时候,flag=1
那么flag =0就代表用户输入的用户名不存在
3、读写模式打开文件对象(先读后写)
1、读文件,遍历文件对象,将字符串strip去换行符后,用split拆分成列表;
2、将列表[-1]转换成int,便于登录次数计算
3、将把文件中的2行字符串,分别作为列表添加这里空列表1变量中
4、用户输入用户名raw-input
5、几个场景
# 1 用户名为空:len(用户名)==0
# 2 用户名不存在:flag =0
# 3 用户名存在: 用户输入的用户名==子列表[0]
# a 用户名和密码都正确 登录次数改为0 break退出当前循环 sys.exit()退出整个程序
# b 密码错误 登录次数+1(列表中) 将修改后的列表转换成字符串,写入到文件
3、遍历内部含有2个列表的列表
4、内层定义一个while True死循环,用于用户输入密码(密码输入不对的话,会一直要求输入,直到break跳出内循环)
1、密码输入raw_input(或者getpass-密码看不见)
2、密码判断(用户名正确的前提下)
1、分支1:密码正确且登录次数小于3,提示登录成功;
2、分支2:登录次数大于等于3,提示用户锁定;
3、分支3、密码错误(登录次数+1),提示还有几次登录机会;
3、将登录次数转换成str
4、将修改后的字符串添加到空列表2
5、判断用户不存在 if flag == 0 ,提示用户不存在,用户重新输入,回到外循环while
6、如果用户存在的话
1、光标seek(0)到文件最开始
2、将修改了登录次数的列表(空列表2中的数据) ,用换行符\n 连接join成一个多行字符串
3、write这个字符串到文件对象
4、关闭文件对象
5、break 跳出外循环
# 整体思路分支:
# 分支1:用户名为空
# 分支2:用户名不存在
# 分支3:用户名密码正确,登录成功,登录此次置为1
# 分支4:用户名正确,但是登录次数大于3,锁定
# 分支5:用户名正确,密码每错误一次,登录次数加1,登录次数为3的时候,锁定
# (这里每次密码错误,只会要求重新输入密码,不用再次输入用户名了)
# 登录接口涉及知识点:
# 1、字典和列表的取值方式:列表通过索引取出用户名、密码、错误登录次数;字典通过key取值
# 2、读写文件
# 1、读文件:1for遍历 2strip去换行 3split拆成列表 4错误登录次数转换成数字,便于计算 5将2个子列表append到空列表中
# 2、写文件:1列表最后一项错误登录次数转换成str 2将列表用;连接符join成字符串作为列表的元素,append到空列表2
# 3光标来到文件最开始seek(0) 4将空列表2的2个元素用连接符\n连接join成一个换行的2行字符串
# 5写入文件 6关闭文件
# 3、多次嵌套循环的跳出
# 4、异常处理:错误登录次数不少数字,锁定
# 5、用户是否存在的标识flag
# 6、颜色提示语
# 加颜色:成功绿色 失败红色
# '\033[32;1m登录成功,欢迎%s\033[0m' --绿色
# '\033[31;1m用户"%s"已锁定,请联系管理员\033[0m' --红色
# 7、getpass不明文显示密码
二、登录验证之流程图:

三、登录验证之用户信息userinfo.txt:
jack;123;0
tom;123;0
四、登录验证之代码:
#!/usr/bin/env python # -*- coding:utf-8 -*- # import getpass import sys while True:#死循环,用于61行输入用户名(用户名输入不对的话,会一直要求输入) old_user_list = [] #计划把文件中的2行字符串,分别作为列表存到这里列表变量中 new_user_list = [] #计划将修改登录次数后的2个字符串作为元素,写入到这个列表变量中 # # 定义一个标识数,来判断用户是否存在 flag = 0 #0的话代表用户名不存在 不是0代表用户名存在(首先用户存在的时候,就将flag置为1; # --用户输入的==子列表的第一个元素(文件中的用户名) # 那么flag==0的时候,就是用户不存咋) f = file('userinfo.txt', 'r+') #读写模式打开文件(先将文件的字符串读入到内存,转换成列表后修改登录次数 #然后将修改后的字符串seek(0)到文件开始,覆盖写入修改后的字符串到文件 ) # 从文件中读取用户信息保存到用户列表内 for line in f: #遍历文件(读取文件字符串到内存 1拆成列表 2将登录次数转换成int,便于计算 3、将2个列表作为元素添加到空列表) # print line, #"jack;123;3" tmp_line_list = line.strip().split(';') #将字符串去掉换行符后,用";"作为分隔符,拆分成列表 # 将用户登录错误次数转为int类型,如果转换失败,将用户锁定 # print tmp_line_list #['jack', '123', '0'] ['tom', '123', '0'] try: tmp_line_list[-1] = int(tmp_line_list[-1]) #将列表的最后一项-登录次数转换成int,用于计算 except ValueError, e: tmp_line_list[-1] = 3 old_user_list.append(tmp_line_list) #将2个列表作为元素添加到空白列表中 # print old_user_list #[['jack', '123', 0], ['tom', '123', 0]] username = raw_input('请输入用户名: ').strip() #将输入的用户名去掉2边空格 if len(username) == 0: #判断输入的用户名是否为空 print '\033[31;1m用户名不能为空!\033[0m' #提示有颜色 continue #跳出当次迭代(当次循环),回到最外层的while死循环,重新输入用户名 for user_line in old_user_list: #遍历内部含有2个列表的列表,和while和for循环有点区别 #print user_line #['jack', '123', 0] ['tom', '123', 0] if username == user_line[0]: #判断输入的用户名是否等于子列表的第一个元素(文件中的用户名) # # 用户存在标识数加1 # print user_line[0] flag = 1 while True: #定义一个内部的while死循环,用于73行输入密码(密码输入不对,会一直要求输入,除非break) password = raw_input('请输入密码: ') #输入密码 if password == user_line[1] and user_line[-1] < 3: #判断输入的密码等于子列表的第2个元素(文件中的密码)且登录次数小于3 # 用户登录成功后将错误次数重置为0 # print user_line[1] user_line[-1] = 0 #将登录次数置为0 print '\033[32;1m登录成功,欢迎%s!\033[0m' % username #提示成功,提示语有颜色,成功显示绿色(亮青色) break #跳出内部的while循环(不会再要求输入密码) 走到106行 # sys.exit() #引发一个 SystemExit异常,若没有捕获这个异常,Python解释器会直接退出 elif user_line[-1] >= 3: #如果登录次数大于等于3 print '\033[31;1m用户"%s"已锁定,请联系管理员!\033[0m' % username #提示语有颜色,失败显示红色 # time.sleep(3) break #sys.exit() #引发一个 SystemExit异常,若没有捕获这个异常,Python解释器会直接退出 else: # 用户名正确,密码错误 # 用户名正确,密码错误,错误次数加1 user_line[-1] += 1 #子列表的最后一项-登录次数加1 # 获取剩余尝试次数 rest_nums = 3 - user_line[-1] #定义剩余的尝试次数 # 如果尝试次数为0,则不再允许尝试 if rest_nums == 0: #如果剩余尝试次数是0 print '\033[31;1m用户"%s"已锁定,请联系管理员!\033[0m' % username #失败显示红色 flag = 3 break#跳出内部的while循环(不会再要求输入密码) 走到106行 else: print "\033[31;1m密码错误!您还可以尝试%d次,错误3次后用户将被锁定,登录成功后错误次数将重置!\033[0m" % rest_nums #失败显示红色 这里没有break,会重复3次提示输入密码,直到锁定 # continue 这里可以注释continue,因为内循环中continue后没有代码,加和不加效果一样 # 将用户错误次数转为str类型 user_line[-1] = str(user_line[-1]) #前面56行转换成数字,为了计算,现在要存储到文件,应该转换成str类型 # 将用户信息转为以“;”分割的字符串,添加到新的用户列表 new_user_list.append(';'.join(user_line)) #将修改后的字符串添加到新的空白列表 # print new_user_list #['jack;123;0', 'tom;123;0'] if flag == 0: #flag=0 标识用户名不存在 print '\033[31;1m用户名不存在,请重新输入!\033[0m' #重新输入用户名,到了58行 失败显示红色 else: #表示用户名存在的所有情况,将修改完登录次数的列表转换成字符串写入到文件 f.seek(0) #回到文件最开始处,将内存中存储的字符串写入到文件对象,覆盖之前的文件内容 # 将新的用户列表转为以“\n”为分割的字符串,写入到用户信息文件 f.write('\n'.join(new_user_list)) #字符串在文件中是分行存储的,所以用\n换行 # print '\n'.join(new_user_list) #jack;123;0\ntom;123;0 f.flush() f.close() #关闭文件对象 break #跳出外循环while #sys.exit() #引发一个 SystemExit异常,若没有捕获这个异常,Python解释器会直接退出 #跳出外循环while # f.seek(0) #用户名不存在的时候,执行下述代码,此处代码可以注释 # # 将新的用户列表转为以“\n”为分割的字符串,写入到用户信息文件 # f.write('\n'.join(new_user_list)) # # print '\n'.join(new_user_list) # f.flush() # f.close()
五、三层菜单之readme:
# 整体思路:
# 1 将省市区行政区划用字典列表来构造,用key取省或者地市列表,用for遍历显示字典或者列表的元素
# 2 根据整个字典的key,得到省列表,遍历打印省的名字列表
# 3 设置用于跳出外循环的flag(跳出嵌套循环)
# 4 两层嵌套循环,外循环for指定3次固定循环,3次输入省名字错误,程序退出(在外循环for后,通过else来实现)
# 内循环while True是死循环,不指定次数(地市名字输入错误后,会一直要求输入,直到输入正确为止),
# 通过break退出内循环
# 5 通过整个字典的key得到省列表,通过省字典的key得到地市列表,遍历打印地市的名字列表
# 6 判断输入的地市是否在省字典中,在的话,通过省字典的key,for遍历打印区县的名字列表
# 不在的话,提示"输入的地市名字不对,请重新输入",continue跳出当次迭代(循环),继续输入地市名字
# 还在内循环while中
# 7 打印区县列表后,2个选择,1是退出整个程序(2个嵌套循环都退出),2是回到上一级别菜单(只需要退出内循环的当前迭代)
# 8 回到上一级别菜单(只退出内循环while) 判断用户输入的是否是"b",是的话,continnue 退出内循环的当前迭代,开始内循环下次迭代
# 9 退出整个程序(2个嵌套循环都退出) 判断用户输入的是否是"q",是的话,先将flag变成True,然后break退出while内循环
# 再做一个判断,判断flag是否是True,如果是的话,break退出for外循环,至此,退出整个程序(2个嵌套循环都退出)
六、三层菜单之流程图:

七、三层菜单之代码:
__author__ = 'Administrator' # -*- coding:utf-8 -*- # 三级菜单--嵌套循环 # 可依次选择进入各子菜单 # 所需新知识点:列表、字典 # 1北京 # 1、海淀 # 2、朝阳 # 3、昌平 # 1、沙河 # 2、天通苑 # 3、回龙观 # b是返回上一级菜单--continue(跳出内循环的当次迭代) # q是退出整个循环--break(退出多层嵌套) # 2,上海 # 3、hk # 整体思路: # 1 将省市区行政区划用字典列表来构造,用key取省或者地市列表,用for遍历显示字典或者列表的元素 # 2 根据整个字典的key,得到省列表,遍历打印省的名字列表 # 3 设置用于跳出外循环的flag(跳出嵌套循环) # 4 两层嵌套循环,外循环for指定3次固定循环,3次输入省名字错误,程序退出(在外循环for后,通过else来实现) # 内循环while True是死循环,不指定次数(地市名字输入错误后,会一直要求输入,直到输入正确为止), # 通过break退出内循环 # 5 通过整个字典的key得到省列表,通过省字典的key得到地市列表,遍历打印地市的名字列表 # 6 判断输入的地市是否在省字典中,在的话,通过省字典的key,for遍历打印区县的名字列表 # 不在的话,提示"输入的地市名字不对,请重新输入",continue跳出当次迭代(循环),继续输入地市名字 # 还在内循环while中 # 7 打印区县列表后,2个选择,1是退出整个程序(2个嵌套循环都退出),2是回到上一级别菜单(只需要退出内循环的当前迭代) # 8 回到上一级别菜单(只退出内循环while) 判断用户输入的是否是"b",是的话,continnue 退出内循环的当前迭代,开始内循环下次迭代 # 9 退出整个程序(2个嵌套循环都退出) 判断用户输入的是否是"q",是的话,先将flag变成True,然后break退出while内循环 # 再做一个判断,判断flag是否是True,如果是的话,break退出for外循环,至此,退出整个程序(2个嵌套循环都退出) #将省市区行政区划用字典列表来构造,用key取省或者地市列表,用for遍历显示字典或者列表的元素 city_map = { "湖北":{"武汉":["武昌","汉阳","汉口"], "黄冈":["黄州","红安","麻城"]}, "吉林":{"长春":["高新区","南关区"], "四平":["东区","西区"]}, } #定义一个字典 print "--------地图------" for i in city_map: #遍历字典的key,列出省市的名字 print i print "------------------" jump_flag = False #用于跳出外循环 for i in range(3): #外循环,指定循环3次,3次外循环完了,就退出程序 city_name = raw_input("请输入你要查看的省市名字:") if city_name in city_map: #检查输入的省是否在地图中,如果省名字3次输入错误,走到60行,程序退出 sheng_name = city_map[city_name] #使用输入的信息作为key,取出省信息,存在字典中 shi_name =sheng_name.keys() #取出省中有哪些地市,存在列表中 while True: #内循环,死循环,不指定循环次数,通过break或者flag跳出 print "----包含的市是----" #友好的提示,分隔线 for i in shi_name: #遍历列表,取出地市名字,打印出来 print i print "------------------" #友好的提示,分隔线 shi_name_input = raw_input("请输入你要查看的地市名字:") if shi_name_input in shi_name: #判断输入的地市名字是否在地市列表中 quxian_name = city_map[city_name][shi_name_input] #取出地市中有哪些区县,存在列表中 print "----包含的区县是----" #友好的提示,分隔线 for i in quxian_name: #遍历列表,取出区县名字,打印出来 print i print "-------------------" #友好的提示,分隔线 if shi_name_input not in shi_name: #如果输入的地市名字不在在地市列表中 print "输入的地市名字不对,请重新输入" continue #跳出当次迭代,开始下一次迭代循环,直到地市名字输入正确为止 jump_shi = raw_input("请问是否退出?按b是返回上一级菜单;按q是退出整个程序") #显示完区县后,就要退出程序了,一个是全部退出,一个是返回上一级菜单 if jump_shi == "q": jump_flag = True #用于跳出外循环 break #跳出while内循环 if jump_shi == "b": continue # 跳出当次迭代,开始下一次迭代循环,来到41行,重新输入地市处,返回上一步 print "你输入的信息有误,请重新输入" if jump_flag: #跳出外循环的条件满足 break #跳出外循环 else:#上面的3次for循环正常执行完毕,else才会执行,如果是不正常退出(break),else不会执行 print "3次输入错误,程序退出"
浙公网安备 33010602011771号