python第十五课--近期关键的几个代码练习,及总结
1.利用有参装饰器编写多种用户登录校验策略
"""
1.直接写死的 jason 123
2.数据来源于列表 ['jason|123','kevin|321','tony|222']
3.数据来源于文件 jason|123\n tom|321\n
"""
有参装饰器套路模板:
def login_auth(condition):
def outer(func):
def inner(*args, **kwargs):
username = input('shuruyonghuming')
password = input('shurumima')
if condition == 'absolut':
if username == 'jason' and password == '123':
res = func(*args, **kwargs)
return res
if condition == 'list_type':
l1 = ['jason|123', 'kevin|321', 'tony|222']
for i in l1:
realname, realpwd = i.split('|')
if realname == username and realpwd == password:
res = func(*args, **kwargs)
return res
if condition == 'file_type':
with open(r'a.txt', 'r', encoding='utf8') as f:
for i in f:
realname,realpwd = i.split('|')
if realname == username and realpwd.strip('\n') == password:
res = func(*args, **kwargs)
return res
return res
return inner
return outer
@login_auth('absolut')
def index():
print('打印index')
index()
@login_auth('list_type')
def fooo():
print('打印aaa')
fooo()
@login_auth('file_type')
def qqqqq():
print('打印cccccccc')
qqqqq()
2. 二分法求列表里面的数字
l2 = [1,2,3,4,5,6,7,8,11,22,33,44,55,66]
def two_sep(l1,target_num):
if len(l1) == 0:
print(l1)
return
n = len(l1)//2
if target_num > l1[n]:
right_l1 = l1[n+1:] # 注意这个地方的切片的时候一定是n+1,特殊情况比如目标值为58,当 切到[55,66]时候就不对,这个时候索引1对应的是66,目标值比66小所以走下面的if,切片[0:1]顾头不顾尾,切出一个55出来继续循环时就出问题了,此时此时len为1,整除2等于0,55比58小,走上面的if条件,如果括号里面[n:],这个时候就切出来的还是55,就陷入死循环了,但是[n+1:]这个时候就切出了空列表了,这个时候再循环就直接结束了!!!
print(right_l1)
return two_sep(right_l1,target_num)
if target_num < l1[n]:
left_l1 = l1[:n]
print(left_l1)
return two_sep(left_l1,target_num)
else:
print('zhaodaole')
two_sep(l2,99)
3. 周测试 较简单
1.编写⽤户识别程序 要求: 可循环根据⽤户输⼊的姓名不同输出不同的身份信息
添加程序结束功能(如⽤户输⼊字⺟q直接结束识别程序) jason:扫地僧 tony:洗碗⼯ kevin:服务员 jack:配菜员 其他: 未识别
d1 = {'jason':'扫地僧',
'tony':'洗碗工',
'kevin':'服务员',
'jack':'配菜员'
}
while True:
username = input('请输入用户名>>>q:')
if username == 'q':
break
if username in d1:
user_info = d1.get(username)
print(user_info)
else:
print('未识别身份')
2.利⽤for循环及range⽅法⾃动⽣成链家⼆⼿房多⻚数据⽹址(⼗条以 上即可)
初始⽹址:https://sh.lianjia.com/ershoufang/
第二页 https://sh.lianjia.com/ershoufang/
第二页 https://sh.lianjia.com/ershoufang/pg2/
第三也 https://sh.lianjia.com/ershoufang/pg3/
第十页 https://sh.lianjia.com/ershoufang/pg10/
for i in range(11):
print(f'https://sh.lianjia.com/ershoufang/pg{i}/')
3.编写⽤户登录程序
温馨提示: ⽤户名与密码来源于字符串source_data = 'jason|123' 想办法从中拆分出⽤户名和密码⽤于后续账户信息⽐对
普通要求: 1.验证失败情况下可⼀直循环验证 成功则直接退出
拔⾼练习: 1.只允许三次失败机会 2.登录成功后进⼊内层循环,⽤户输⼊任何指令利⽤格式化输出 打印正在执⾏该⽤户指令即可,
直到⽤户输⼊字⺟q退出内层循环
普通要求:
source_data = 'jason|123'
while True:
username = input('输入用户名')
password = input('输入密码')
userdate = username + '|' + password
if userdate == source_data:
print('登录成功')
break
else:
print('请重新输入密码')
# userdate = f'{username}|{password}'
还可以realname,realpwd = source_data.split('|')
if realname == username and realpwd == password:
拔⾼练习: 1.只允许三次失败机会 2.登录成功后进⼊内层循环,⽤户输⼊任何指令利⽤格式化输出 打印正在执⾏该⽤户指令即可,
直到⽤户输⼊字⺟q退出内层循环
source_data = 'jason|123'
count = 0
while count < 4:
username = input('输入用户名')
password = input('输入密码')
userdate = f'{username}|{password}'
if realname == username and realpwd == password:
if userdate == source_data:
while True:
zhiling = input('请输入您想要的指令')
print('zhiling')
if zhiling == 'q':
break
else:
print('请重新输入密码')
else:
print('您已经输错3次了')
还可以realname,realpwd = source_data.split('|')
。
4. 利用装饰器对多个函数运行前,要求:
从user_data中校验用户身份是否正确
并获取当前登录用户拥有的可执行函数功能编号即键access对应的功能编号列表
并且一旦用户登录成功之后后续函数的调用不再校验用户身份
请思考如何获取函数功能编号 如何校验用户身份 如何校验权限?
代码编写思路:
"""
1.先写装饰器模板
2.再写用户校验
3.记录用户登录状态
4.再考虑用户权限问题
"""
1. 首先用户的登录状态的校验的代码运行一定在,输入用户名账号密码校验程序的前面。先判断有没有登陆过,登录过了就不用再登录了
2. 登录状态校验后,还要再校验该被装饰函数体的编号是不是在获取的access的里面。假设,如果用户的登录状态为登录过了,并且要运行的函数编号也在该用户的权限里面,此时说明该用户有权限执行该函数代码,那么这个时候就应该直接运行被装饰的函数代码了 res=func(*args,**kwargs) return res 。
3. 假设用户登录状态已经为登录过了,这个时候如果要运行的函数编号不在该用户的权限里面,说明此时用户已经没有权限执行该函数了,这个时候就应该直接结束该装饰器的整体的运行,不用再让用户输入账号密码了。
4. 现在如何实现用户登录状态的判断?已经一旦用户再登陆过一次后,登录状态的可以发生改变,装饰器在装饰其他函数后,当其他的被装饰函数在运行前的登录状态的校验时,这个时候可以发现登录状态已经发生改变。如果发现已经登录了,在判断该被装饰函数的编号在不在该用户 对应的access里面。
5.要实现登录过一次后, 用户的登录状态要被记录,用户的权限也要被记录,这样后续只要判断登录过了,函数的编号在权限里面,就可以直接不用登录直接运行被装饰的函数体代码了
有下列用户数据
user_data = {
'1': {'name': 'jason', 'pwd': '123', 'access': ['1', '2', '3']},
'2': {'name': 'kevin', 'pwd': '321', 'access': ['1', '2']},
'3': {'name': 'oscar', 'pwd': '222', 'access': ['1']}
}
并有三个函数
def func1():
pass
def func2():
pass
def func3():
pass
要求:调用上述三个函数的时候需要从user_data中校验用户身份是否正确
并获取当前登录用户拥有的可执行函数功能编号即键access对应的功能编号列表
func1是1、func2是2、func3是3
并且一旦用户登录成功之后后续函数的调用不再校验用户身份
请思考如何获取函数功能编号 如何校验用户身份 如何校验权限
ps:装饰器知识 附赠:实现上述主体功能即可 其他扩展优化功能可暂且不写
代码实现:
user_data = {
'1': {'name': 'jason', 'pwd': '123', 'access': ['1', '2', '3']},
'2': {'name': 'kevin', 'pwd': '321', 'access': ['1', '2']},
'3': {'name': 'oscar', 'pwd': '222', 'access': ['1']}
}
# 当然了记录用户登录状态与权限也可以用两个列表分开来记录,但是那样代码不简洁,没有字典方便。
d1 = {
'status': False, # 记录用户是否登录
'access': [] # 记录登录用户的权限 这地方必须是空列表不能是None,会报错
}
def login_auth(n):
def outer(func):
def inner(*args,**kwargs):
if d1.get('status'):
if n in d1.get('access'): # 校验函数编号在不在用户权限里
res = func(*args,**kwargs)
return
else:
print(f'您没有功能编号为{n}的函数执行权限aaaa')
return # 注意这个地方return不能忘掉,比如用户已经登录过了,运行下一个被装饰的函数时,发现该函数的编号不在该用户的权限里面,这个时候就应该直接结束装饰器的运行了,否则就会出现已经判断出该用户已经没权限运行该函数后,还要再往下走判断用户的id,输入账号密码等代码了!!!
user_id = input('请输入您的id').strip()
if user_id not in user_data: # 这个地方取反会对后续代码的编写方便点
print('用户的id不存在,无法完成身份的校验')
return
username = input('请输入用户名').strip()
password = input('请输入密码').strip()
user_dict = user_data.get(user_id)
if username == user_dict.get('name') and password == user_dict.get('pwd'):
d1['status'] = True # 登录成功后立即记录当前用户的登录状态
d1['access'] = user_dict.get('access') # 记录当前用户的权限编号
if n in user_dict.get('access'): # 注意登录成功还是要校验当前函数编号在不在用户的权限里面
res = func(*args,**kwargs)
return res
else:
print(f'您没有功能编号为{n}的函数执行权限bbbb') # 这边就不用return了,因为走到往下也没有代码
else:
print('用户名或密码错误') # 这边就不用return了,因为走到往下也没有代码
return inner
return outer
@login_auth('1') # 这个地方1一定要用引号引起来!!!!!
def func1():
print('from 111aaa')
@login_auth('2')
def func2():
print('from 222bbb')
@login_auth('3')
def func3():
print('from 333ccc')
func1()
func2()
func3()
注意:无论你是登录过了还是没登录过,在运行被装饰函数前都要先较验函数的编号在不在用户的权限中,只要不在权限中,你就算登录了,也不能执行被装饰的函数代码的运行!!!!
5.编代码时发现问题
列表与字典等可变数据类型数据,一旦发生了修改,原来引用列表变量名的数据比如列表或者字典里面的数据都会发生改变!!!
所以要想原来引用列表变量名的数据,不随列表的改变而改变,就必须在对列表数据进行修改前,先将原来列表的内存地址与变量名的绑定关系解除,比如 定义一个空列表绑定给原列表的变量名,这样原列表绑定的内存地址就只与引用它的数据里面的索引或键有绑定关系了。
。
6. 要求将字符串信息转变为列表套字典的形式
str1 = """id,name,age,phone,job
1,alex,22,13651054608,IT
2,wusir,23,13304320533,Tearcher
3,老男孩,18,1333235322,IT"""
# 要求:将上面的字符串里面的信息变成下面形式
# info = [{'id':'1','name':'alex','age':'22','phone':'13651054608','job':'IT'},
# {'id':'2','name':'wusir','age':'23','phone':'13304320533','job':'Tearcher'},
# {'id':'1','name':'alex','age':'22','phone':'13651054608','job':'IT'}
# ]
代码实现:
list_date = []
dict1 = {}
str1, str2 = str1.split("\n", maxsplit=1) # 1 分开整体字符串的第一行并解压赋值给l1
l1 = str1.split(",") # 2 字符串切割后生成列表l1
for i in l1: # 3 对列表l1进行for循环,
dict1[i] = None # 4 将键值对添加到空字典里面去
# 空一行方便看
l2_3str = str2.split("\n") # 5 剩下的字符串按换行符切割成3个字符串生成列表l2_3str
for j in l2_3str: # 6 对列表l2_3str进行for循环,拿出单行的字符串
l3_info = j.split(',') # 7 对单行字符串再进行切割,生成列表l3_info
dict1["id"] = l3_info[0]
dict1["name"] = l3_info[1] # 8 对列表l3_info进行索引取值,并将其作为值塞到字典dict1里面去
dict1["age"] = l3_info[2]
dict1["phone"] = l3_info[3]
dict1["job"] = l3_info[4]
list_date.append(dict1) # 9 将dict1作为一个字典添加到列表list_date里面去
dict1 = {} # 10
print(list_date)
# 10 此处不是将字典清空,而是将空字典赋值给变量名dict1,那么原字典的内存地址就与dict1变量名解除绑定了,
# 但是大列表里面的索引还是与原字典的内存地址绑定的,所以大列表里面的原字典数据不会被垃圾回收机制清除掉,
# 同理第二for循环后将字典数据添加到列表里面后,再次将空字典赋值给变量名dict1,这个时候变量名dict1又与刚刚绑定的字典内存地址解除绑定了
要求:将列表l1变成字典{'k1': [11, 22, 33, 44, 55], 'k2': [66, 77, 88, 99]}
l1 = [11,22,33,44,55,66,77,88,99]
代码是实现:
l1 = [11,22,33,44,55,66,77,88,99]
d1 = {'k1':[],'k2':[]}
for i in l1:
if i < 60:
d1.get('k1').append(i)
if i >60:
d1.get('k2').append(i)
print(d1)
或者这样:
l1 = [11,22,33,44,55,66,77,88,99]
l2 = []
l3 = []
for i in l1:
if i < 60:
l2.append(i)
if i > 60:
l3.append(i)
d1 = {}
d1['k1']=l2
d1['k2']=l3
print(d1)
练习题
def dec(f):
n = 3 # 2.n = 3
def wrapper(*args, **kw): # 3.定义wrapper(*args, **kw)
return f(*args, **kw) * n # foo(2) * 3
return wrapper # 4.返回wrapper,传给foo,foo()=wrapper()
@dec # 1.foo = dec(foo) f = foo
def foo(n):
return n * 2
res = foo(2) # 5.foo(2)就是wrapper(2),运行wrapper函数体代码
print(res)
# 6 这个时候f就是foo,而且这个foo是实际的foo,所以foo(2)*n 结果等于2*2*3 结果就是12
1.编写简易版本的拷贝工具
souce_file_path = input('请输入您想要拷贝的文件路径').strip()
target_file_path = input('请输入您想要拷贝到的地方路径').strip() # 注意这个地方的路径要包括生成的文件名!!
with open (r'%s'% souce_file_path,'rb')as read_f,open(r'%s'% target_file_path,'wb') as write_f:
for i in read_f:
write_f.write(i)
注意这个文件里面要么是纯空的txt文件!!!注意空的txt文件里面一定不要有两行空行!!!
有两行空行,第一行空行默认就有一个换行符\n 这样运行到切割解压赋值操作时就一直报错!!
如果想往txt里面提前写数据,那么注意一定要在比如输入jason|123后回车换到下一行!!!
这样123后面就默认有了一个换行符了,所以追加模式往里面写的时候就会往下一行写了!!!不会连在123后面写了
注意不管txt文件里面有没有数据,一定要留意里面有没有多余的空行,只要多一行空行,for循环到这一行多余的空行时,split('|')切割时解压赋值时就出问题了,会一直报错!!!
# 文件名称:userinfo.txt
!
# 基础要求:
# 用户注册功能>>>:文件内添加用户数据(用户名、密码等) 1
# 用户登录功能>>>:读取文件内用户数据做校验 2
# ps:上述功能只需要实现一次就算过关(单用户) 文件内始终就一个用户信息
# 考虑到在用户注册时,如果用户名已经注册的情况!!!
# 用户可以连续注册
# 用户可以多账号切换登录(多用户) 文件内有多个用户信息
# ps:思考多用户数据情况下如何组织文件内数据结构较为简单
# 提示:本质其实就是昨天作业的第二道题 只不过数据库由数据类型变成文件
while True:
print("""
1.注册功能
2.登录功能
""")
func_n = input('请输入功能编号')
if func_n == '1':
username = input('请输入用户名').strip()
password = input('请输入密码').strip()
with open(r'userinfo.txt','r',encoding='utf8')as f:
for i in f:
realname,realpwd=i.split('|')
if realname == username:
print('用户名已存在,无法完成注册')
break
else: # 注意这个地方else不能与if平行
with open(r'userinfo.txt','a',encoding='utf8')as f1: # a 是追加模式打开,
f1.write(f'{username}|{password}\n') # 写入用户名与密码的字符串
print(f'用户{username}注册成功')
elif func_n == '2':
username = input('请输入用户名').strip()
password = input('请输入密码').strip()
with open(r'userinfo.txt', 'r', encoding='utf8')as f:
for i in f:
realname, realpwd = i.split('|')
if realname == username and realpwd.strip('\n')==password:
print('登录成功')
else:
print('用户密码错误')
else:
print('没有该功能编号111')
实现图片验证码
'''产生图片验证码: 每一位都可以是大写字母 小写字母 数字 随机的 先想生成4位'''
主体功能代码:
import random
for i in range(4): # 循环4次 产生随机的大写字母 小写字母 数字
upper1 = chr(random.randint(65,90)) # 1.基于ASCII码 数字转字母A-Z
lower1 = chr(random.randint(97,122)) # 2.a-z
int1 = random.randint(0,9) # 随机0-9 的数字
temp = random.choice([upper1,lower1,int1]) # 随机三选一
print(temp,end='') # 去掉自动换行,4个字符串就连起来了
拔高
优化版代码:
import random
def getcode(n):
for i in range (n):
upper1 = chr(random.randint(65,90))
lower1 = chr(random.randint(97,122))
num1 = random.randint(0,9)
temp = random.choice([upper1,lower1,num1])
print(temp,end='')
getcode(10)
或者利用返回值的形式:
def get_code(n):
code = ''
for i in range(n):
# 1.先产生随机的大写字母 小写字母 数字
random_upper = chr(random.randint(65, 90)) # 基于ASCII码 数字转字母A-Z
random_lower = chr(random.randint(97, 122)) # a-z
random_int = str(random.randint(0, 9)) # 因为整形与字符串不能相加,所以加个str 把数字转为字符串
temp = random.choice([random_upper, random_lower, random_int]) # 2.随机三选一
code += temp # 字符串的拼接操作
return code
res = get_code(10)
print(res)
res = get_code(4)
print(res)
# 员工管理系统
# 员工管理系统:注册、查看(单个员工、所有员工)、修改薪资、删除员工
# 用如下的字典形式存放用户数据
# d1 = {
# '1':{'name':'jason','age':18, 'job':'teacher', 'salary':8000},
# '2':{'name':'kevin','age':28, 'job':'sale', 'salary':9000},
# '3':{'name':'jason','age':18, 'job':'teacher', 'salary':8000},
# }
user_date_dict = {}
while True:
print("""
1.注册功能
2.查看员工信息
3.查看所有员工信息
4.修改薪资
5.删除员工
""")
func_n = input('请输入想执行的功能编号>>:')
if func_n == '1':
while True:
num1 = input('请输入用户编号>>q')
if num1 == 'q':
break
if not num1.isdigit: # 判断是不是数字
print('员工编号必须是纯数字')
continue
if num1 in user_date_dict:
print('用户名已注册,请重新录入')
continue
username = input('请输入用户名').strip()
userage = input('请输入年龄').strip()
userjob = input('请输入工作').strip()
usersalary = input('请输入薪资').strip()
d1 = {} # 定义一个空字典接收员工信息
d1['num'] = num1
d1['name'] = username
d1['age'] = userage
d1['job'] = userjob
d1['salary'] = usersalary
user_date_dict[num1] = d1
print(f'员工{username}信息已添加成功')
print(user_date_dict)
if func_n == '2':
while True:
num2 = input('请输入员工编号>>q')
if num2 == 'q':
break
if num2 not in user_date_dict:
print('员工编号不存在 无法查看')
continue
d2 = user_date_dict.get(num2)
print(f"""
-------------------info--------------
编号:{d2.get('num')}
姓名:{d2.get('name')}
年龄:{d2.get('age')}
岗位:{d2.get('job')}
薪资:{d2.get('salary')}
-------------------------------------
""")
if func_n == '3': # 查看所有员工信息
for i in user_date_dict.values(): # 取出大字典中的小字典,并for循环
print(f"""
-------------------info--------------
编号:{i.get('num')}
姓名:{i.get('name')}
年龄:{i.get('age')}
岗位:{i.get('job')}
薪资:{i.get('salary')}
-------------------------------------
""")
if func_n == '4': # 修改员工信息
num4 = input('请输入想要修改的员工编号>>Q').strip()
if num4 == 'q':
break
if num4 not in user_date_dict:
print('员工编号不存在')
continue
if not num4.isdigit():
print('薪资只能是纯数字')
continue
d4 = user_date_dict.get(num4)
new_salary = input('请输入该员工新的工资待遇').strip()
d4['salary'] = new_salary
user_date_dict[num4] = d4
print(user_date_dict.get(num4))
if func_n == '5': # 删除员工信息
while True:
num5 = input('请输入您要删除的员工编号q>>:')
if num5 == 'q':
break
if not num5.isdigit():
print('该员工编号不存在')
continue
user_date_dict.pop(num5)
print('已删除该员工信息')
if func_n not in user_date_dict:
print('没有您想要执行的功能')
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 开源Multi-agent AI智能体框架aevatar.ai,欢迎大家贡献代码
· Manus重磅发布:全球首款通用AI代理技术深度解析与实战指南
· 被坑几百块钱后,我竟然真的恢复了删除的微信聊天记录!
· 没有Manus邀请码?试试免邀请码的MGX或者开源的OpenManus吧
· 园子的第一款AI主题卫衣上架——"HELLO! HOW CAN I ASSIST YOU TODAY