流程控制就是控制程序执行的流程。流程控制分三种结构:顺序结构(程序从上往下执行最后结束);分支结构(通过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=2	2x2=4
3x1=3	3x2=6	3x3=9
4x1=4	4x2=8	4x3=12	4x4=16
5x1=5	5x2=10	5x3=15	5x4=20	5x5=25
6x1=6	6x2=12	6x3=18	6x4=24	6x5=30	6x6=36
7x1=7	7x2=14	7x3=21	7x4=28	7x5=35	7x6=42	7x7=49
8x1=8	8x2=16	8x3=24	8x4=32	8x5=40	8x6=48	8x7=56	8x8=64
9x1=9	9x2=18	9x3=27	9x4=36	9x5=45	9x6=54	9x7=63	9x8=72	9x9=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')