流程控制就是控制程序执行的流程。流程控制分三种结构:顺序结构(程序从上往下执行最后结束);分支结构(通过if判断);循环结构(for循环、while循环)
分支结构
分支结构:通过判断条件的真假,选择执行不同的子代码块。
实现方式:通过if语句
if语法
完整定义
if 条件1:
代码块1
elif 条件2:
代码块2
elif 条件3:
代码块3
else:
代码块4
# 代码块指的是相同缩进的一堆代码。python通过缩进4个字符位控制不同的代码块。
# 当条件1为真时,程序执行代码块1;代码块1执行结束后,程序将不再执行该if语句引导的后续elif和else下面的子代码块
# 当条件1为假,程序将依次判断后续elif后面的条件是否为真,直到找到一个为真的条件并执行相应的子代码快;如果所有的elif条件都不满足,则执行else后面的子代码块4
# if 也可以单独使用,不接elif 或 else
# 什么是条件
第一大类:显式布尔值
1, 条件可以是:True、False
2, 条件可以是 逻辑运算符表达式
第二大类:隐式布尔值,所有的值都可以当成条件去用
其中0、None、空(空字符串、空列表、空字典)=》代表的布尔值为False,其余都为真
if使用案例
案例1:
# 如果成年可以登录
age = 18
if age >= 18:
print("登录成功")
else:
print("未成年禁止登录")
案例2:
# 学生成绩划分等级
score = 82
if 90 < score <= 100:
print("A")
elif 80 < score <= 90:
print("B")
elif 70 < score <= 80:
print("C")
elif 60 < score <= 70:
print("D")
else:
print("E")
案例3:
# if 嵌套使用
username= "jack"
password = "1235"
if username == "jack":
if password == "12345":
print("登录成功")
else:
print("密码错误,登录失败")
else:
print("用户名错误,登录失败")
循环结构
循环结构:让程序循环执行形同的代码块
实现方式:while循环、for循环
while循环
语法定义
while 条件:
代码块
# 当条件为真时,执行代码块
# 使用while循环,一定要注意循环条件,避免出现死循环
死循环
while True:
print(1)
# 该while循环,循环条件一直为True,程序将一直不停的执行,即出现死循环。
# 大多数情况下,我们应该再程序中避免出现死循环。
while循环使用案例
案例一:账号登录,三次登陆机会
username = 'jack'
password = '12345'
count = 3
while count > 0:
name = input("请输入用户名>>>:")
pawd = input("请输入密码>>>:")
if name == username and pawd == password:
print("登录成功")
else:
print("用户名或密码错误,请重新登录")
count -= 1
# 该程序有一个bug,就是用户登录成功后,循环还在继续
案例二:账号登录,三次登陆机会,登录成功后推出循环
知识点:程序遇到break,将立即停止break所在循环体内后续所有代码的执行,终止并跳出循环。
username = 'jack'
password = '12345'
count = 3
while count > 0:
name = input("请输入用户名>>>:")
pawd = input("请输入密码>>>:")
if name == username and pawd == password:
print("登录成功")
break# 登录成功后,执行break语句,将结束while循环
else:
print("用户名或密码错误,请重新登录")
count -= 1
案例三:账号登录,三次登陆机会。while嵌套+break
当程序嵌套多个 while循环时,退出程序需要需要再内层循环添加break
# 当用户登录成功后,进入内层while循环,做相关操作,如果用户输入'q'则推出程序
username = 'jack'
password = '12345'
count = 3
while count > 0:
name = input("请输入用户名>>>:")
pawd = input("请输入密码>>>:")
if name == username and pawd == password:
print("登录成功")
while True:
cmd = input("请输入指令(按q退出)>>>:")
if cmd == 'q':
break
else:
print(cmd)
break
else:
print("用户名或密码错误,请重新登录")
count -= 1
案例四:案例三代码改进版 while嵌套 + tag
当嵌套多层while循环时,从任意一层即可推出程序,可以使用这方方式。
username = 'jack'
password = '12345'
count = 0
tag = True
while tag:
name = input("请输入用户名>>>:")
pawd = input("请输入密码>>>:")
if name == username and pawd == password:
print("登录成功")
while tag:
cmd = input("请输入指令(按q退出)>>>:")
if cmd == 'q':
tag = False
else:
print(cmd)
else:
print("用户名或密码错误,请重新登录")
count += 1
if count == 3:
tag = False
案例五:while+ continue
知识点:程序遇到continue,将立即停止continue所在本次循环的后续代码执行,进入下一轮循环。
对比:break结束本层循环,continue结束本次循环。
# 打印1 2 3 4 5 6 8 9
n = 1
while n <= 9:
if n == 7 :
n += 1
continue
print(n, end=' ')
n += 1
案例六:while + else
知识点:while+else语法,退出while循环的原因不是break就执行else下面的代码块,否则不执行。
flag = 5
n = 1
while n <= 9:
if n == flag :
break
print(n, end=' ')
n += 1
else:
print("我是正常退出的,不是break出来的")
# 当flag = 5时,打印:1 2 3 4
# 当flag = 10时,打印:1 2 3 4 5 6 7 8 9 我是正常退出的,不是break出来的
for循环
for循环时python中的另一种实现循环结构的语法。
for循环的主要优势:方便循环取值(遍历可迭代对象),这种循环取值方式比while循环更加简洁明了。
语法定义
for i in 可迭代对象:
print(i)
# 此处可迭代对象,可以是字符串、列表、字典等数据数据类型,也可以是生成器
# i 是全局变量,程序运行时将一直存在内存中
# 有时仅为了循环,不涉及数据打印和操作,可以使用 _ 占位符;如,
for _ in range(10):
print("Hello world")
同while循环一样,for循环也可以和break、continue、else连用,也可以嵌套循环。
补充:range()
# range(3):默认从0开始,顾头不顾尾,到2结束,返回 [0,1,2]
# range(1,6) # 可以指定开头,从1开始,顾头不顾尾,到5结束,返回 [1 2 3 4 5 ]
# range(1,6,2) # 可以指定步长,返回 [1 3 5]
for循环使用案例
案例一:打印数字1-10
# 打印数字1-10
for i in range(1,11):
print(i)
案例二:打印列表中的所有元素
# 打印列表中的所有元素
names = ["jack", "cindy", "ben", "joy"]
for name in names:
print(name)
# 此处定义变量 name 循环代表列表的个元素
案例三:打印99乘法表
# 打印99乘法表
for i in range(1, 10):
for j in range(1, i+1):
print(f"{i}x{j}={i*j}", end="\t") # 不换行,空格隔开
print(f"{i}x{j}={i*j}") # 一行打印结束,另起一行
# 输出:
1x1=1
2x1=22x2=4
3x1=33x2=63x3=9
4x1=44x2=84x3=124x4=16
5x1=55x2=105x3=155x4=205x5=25
6x1=66x2=126x3=186x4=246x5=306x6=36
7x1=77x2=147x3=217x4=287x5=357x6=427x7=49
8x1=88x2=168x3=248x4=328x5=408x6=488x7=568x8=64
9x1=99x2=189x3=279x4=369x5=459x6=549x7=639x8=729x9=81
# 补充知识点:字符串拼接(f-String),
name = "jack"
output = f"hello {name}"
print(output)# 输出:hello jack
# 等价于
name = "jack"
output = "hello %s" % name
print(output)
总结:
# 总结:
# 一:while循环与for循环
# 相同之处:都是循环,都是用来做重复的事情
# 不同之处
# 1、
# while循环通常用来循环执行某段代码
# for循环通常用来进行循环取值
# 2、
# while循环的循环次数取决于条件什么时候为假
# for循环循环的次数取决in后的数据类型所包含的值的个数
# 二:for+range():range用来产生一个数字序列
# 用途1:用来重新n次某段代码
# 用途2:range可以用来产生数字序列,数字对应的是列表的索引
# 所以说,for+range()是可以按照索引编列列表
实战练习
编写用户登录接口
需求
1 输入账号密码完成验证,验证通过后输出"登录成功"
2 可以登录不同的用户
3 同一账号输错三次锁定(无论程序是否关闭,都锁定5分钟)
思路:
实现不同用户登录,需要一个字典,字典里面存放多个用户的用户名、密码 实现多个用户登录
使用循环结构,程序一开始进入循环,提示输入用户名密码,匹配是否登录成功,登录成功则退出,登录失败则提示登录失败,继续下一次循环
锁定实现:在用户字典中添加登录次数的键值对,用于记录登录登录失败的此时,
登录失败三次时锁定用户5分钟:添加一个新的键值对(时间戳)用于记录用户第三次登录失败的时间,下次登录时比较当前时间与锁定时间差,是否超过5min。
程序关闭后,继续锁定:将用户信息字典转成json文件,保存在本地。
实现功能:
实现多用户登录,登录成功会,打印“登录成功”,并退出
每个用户有三次连续登录失败的机会,一旦超过三次程序将锁定,该用户无法继续登录,必须等待5分钟后才可再次登录。程序关闭也会锁定5分钟。
一个用户账户锁定期间,不影响其他用户正常登录。
版本1.0
login.py
# login.py文件
import time, json
# json文件初始信息
"""
user_info = [
{'name': 'egon', 'pawd': '123456', 'login_fail_nums': 0, 'lock_start_time': 0},
{'name': 'alex', 'pawd': '123456', 'login_fail_nums': 0, 'lock_start_time': 0},
]
"""
# 将内存字典写入json文件
def write(user_info):
res = json.dumps(user_info)
with open('user_info.json', 'w', encoding='utf-8') as f:
f.write(res)
# 读json文件到内存
def read(user_info):
with open(user_info, "r", encoding='utf-8') as f:
content = f.read()
return json.loads(content)
# 从json文件中读取用户信息并放入user_info字典中
user_info = read('user_info.json')
while True:
# 输入用户名
username = input("username >>:")
# 标识输入用户是否存在
user_exist = False
for index in range(len(user_info)):
if username == user_info[index].get('name'):
# 用户存在则理解退出当前循环体,index记录该用户在user_info中的位置
user_exist = True
break
# 如果用户名不存在,则无需输入密码,直接提示账号不存在
if not user_exist:
print("用户名:", username, " 不存在,请重新输入!")
continue
# 账号存在,先验证该账号输入已经登录失败三次,
# 如果是则提示当前解锁中,需等待5分钟后重新解锁该账号
if user_info[index]['login_fail_nums'] == 3:
now = time.time()
passed_time = now - user_info[index]['lock_start_time']
if passed_time > 5*60:
# 冻结时间到,重置登录失败错误次数和冻结时间
user_info[index]['login_fail_nums'] = 0
user_info[index]['lock_start_time'] = 0
# 将修改后的信息保存到硬盘 .json文件
write(user_info)
else:
# 冻结时间未到,继续等待,并提示等后续待时间
print("该账号已锁定", str(300-int(passed_time)), '秒后解锁')
continue
# 该账号存在且未冻结,支持输入密码登录
password = input("password >>:")
if password == user_info[index].get('pawd'):
# 密码匹配,登录成功
user_info[index]['login_fail_nums'] = 0
print("登录成功!")
break
else:
# 密码错误,打印出错提示,并累加登录错误次数
print("密码错误,请重新输入!")
user_info[index]['login_fail_nums'] += 1
#累加后判断登录错误是否满三次,如果已经三次错误登录则冻结账号,设定冻结账号的时间
if user_info[index]['login_fail_nums'] == 3:
user_info[index]['lock_start_time'] = time.time()
print('该账号连续3次登录失败,账号冻结5分钟!')
# 将修改后的信息保存到硬盘 .json文件
write(user_info)
user_info.json
# user_info.json文件
[{"name": "egon", "pawd": "123456", "login_fail_nums": 0, "lock_start_time": 0}, {"name": "alex", "pawd": "123456", "login_fail_nums": 0, "lock_start_time": 0}]
版本2.0
# 扩展需求:
import time
import json
# 从硬盘取数据
def read_account_info(account_info_json):
with open(account_info_json, 'r', encoding='utf-8') as f:
return json.loads(f.read())
# 数据保存硬盘
def write_account_info(account_info_dict):
with open('account_info.json', 'w', encoding='utf-8') as f:
f.write(json.dumps(account_info_dict))
# account_info = {
# 'egon': {'pwd':'123456', 'login_fail_nums': 0, 'lock_time': None},
# 'alex': {'pwd':'123456', 'login_fail_nums': 0, 'lock_time': None}
# }
# 从硬盘去账号信息转为内存中的字典
account_info = read_account_info('account_info.json')
while 1:
username = input('username >>>:').strip()
password = input('password >>>:').strip()
# 判断账号是否存在
if username in account_info:
# 判断账户是否锁定
if account_info[username]['login_fail_nums'] == 3:
# 等待的时间
waited_time = int(time.time() - account_info[username]['lock_time'])
# 等待时间超过5min则账号解锁
if waited_time > 5*60:
account_info[username]['login_fail_nums'] = 0
account_info[username]['lock_time'] = None
# 更新数据到硬盘
write_account_info(account_info)
else:
print(f'account locked, please login after {5*60 - waited_time} s')
continue
# 登录检查
if password == account_info[username]['pwd']:
# 连续三次登录失败才锁定账号
account_info[username]['login_fail_nums'] = 0
write_account_info(account_info)
print('登录成功')
break
else:
# 登录失败,记录失败次数
account_info[username]['login_fail_nums'] += 1
msg = 'wrong username or password, please try again'
if account_info[username]['login_fail_nums'] == 3:
# 记录锁定的那个时刻,时间戳
account_info[username]['lock_time'] = time.time()
msg = 'account locked for max_login_fail_nums exceeded, please login after 5 min'
print(msg)
# 更新数据都硬盘
write_account_info(account_info)
else:
print(f'no account: {username}, please check again')