当前位置: 首页 > news >正文

Day18笔记-会员管理系统函数递归装饰器的使用

一、会员管理系统

根据下面的需求描述,完成简单的用户管理系统,注意封装函数

  1. 后台管理员只有一个用户: admin, 密码: admin

  2. 当管理员登陆账号成功后, 可以管理前台会员信息.

  3. 会员信息管理包含方法:a.添加会员信息b.删除会员信息c.查看会员信息

  4. 对会员按照年龄降序排序

  5. 退出

    思路:1.输入用户名和密码 跟 管理员的账号密码匹配 不一致的话 登陆失败一致的话 提示登陆成功并列出 对应的 1 2 3 4 5的操作 输入对应的编号 执行对应的方法2.会员信息包含:会员编号(mid) ---- 编号是在10000到99999中随机选择一个 不能重复会员姓名(name)会员性别(sex)会员年龄(age)使用字典保存每个会员信息例如{'mid':10000, 'name':'乐乐','sex':'男', 'age':20}使用列表保存所有的会员例如[{'mid':10000, 'name':'乐乐','sex':'男', 'age':20},{'mid':10001, 'name':'美美','sex':'女', 'age':19}]
import  random
​
# 定义列表,存储会员信息
users_list = []
# [{},{}......]
​
# 一、封装函数
def get_mid():while True:mid = str(random.randint(10000,99999))   # 后期查询的时候,从控制台输入会员号无需转化if mid not in [dic['mid'] for dic in users_list]:return mid
def add_user(name,sex,age):mid = get_mid()print(f'你的会员号是:{mid}')users_list.append(dict(zip(['mid','name','sex','age'],[mid,name,sex,age])))print('添加成功!')
def del_user(mid):# 注意:如果确定列表中的元素是唯一的,则删除可以不做拷贝处理,如果要删除的元素在2个及以上,则需要拷贝for user in users_list:if user['mid'] == mid:users_list.remove(user)print('删除成功')breakelse:print('会员信息不存在')
def show_user(mid):for user in users_list:if user['mid'] == mid:print(user)breakelse:print('会员信息不存在')
def sort_user():#  方式一# users_list.sort(key=lambda dic:dic['age'],reverse=True)# print(users_list)# 方式二new_list = sorted(users_list,key=lambda dic:dic['age'],reverse=True)print(new_list)
​
# 二、调用函数
def main():print('管理员登录界面'.center(50, '*'))for i in range(3):# 引导输入管理员的用户名和密码admin_name = input('请输入管理员的用户名:')admin_pwd = input('请输入管理员的密码:')if admin_name == 'admin' and admin_pwd == 'admin':print('管理员登录成功!')print('欢迎进入xxx会员管理系统')# 进入管理系统# 因为进入管理系统之后,具体要做哪些操作,进行几次操作不确定while True:print('''********操作目录**********1.添加会员信息2.删除会员信息3.查看会员信息4.对会员信息排序5.退出''')# 引导管理员执行相应的操作choice = input('请输入需要执行的操作:')if choice == '1':print('添加会员信息'.center(50, '*'))name = input('请输入会员名:')sex = input('请输入会员性别:')age = int(input('请输入会员年龄:'))add_user(name, sex, age)elif choice == '2':print('删除会员信息'.center(50, '*'))mid = input('请输入需要删除的会员号:')del_user(mid)elif choice == '3':print('查看会员信息'.center(50, '*'))mid = input('请输入需要查找的会员号:')show_user(mid)elif choice == '4':print('对会员信息排序'.center(50, '*'))sort_user()elif choice == '5':print('欢迎再次使用')# 此处的break结束的是while死循环break  # 扩展:此处的break可以替换为exit(),表示退出程序# exit()else:print('输入有误,暂无此操作,请输入正确的操作编号')# 此处的break结束的是for循环breakelse:if i == 2:continueprint('管理员登录失败,请重新输入')else:print('已经错误三次,禁止管理员登录')
​
main()

二、函数递归【了解】

函数递归:函数调用自身

处理递归的关键:

​ a.需要找到一个临界值【让程序停止下来的条件】 b.函数相邻两次调用之间的关系

# 1.斐波那契数列
# 需求:报一个数,返回斐波那契数列中该位置的数字
"""
1   2   3   4   5   6   7   8   9   10......
1   1   2   3   5   8  13   21  34  55......
"""
​
#2.求1~100之间所有整数的和
# 1.恶意递归调用
# def a():
#     print('aaaa')
#     a()
# a()
​
# 2.
# a.斐波那契数列
# 需求:报一个数,返回斐波那契数列中该位置的数字
"""
1   2   3   4   5   6   7   8   9   10......
1   1   2   3   5   8  13   21  34  55......
​
分析:求func(5)
第一步
func(5) = func(4) + func(3) = 3 + 2 = 5
第二步:
func(4) = func(3) + func(2) = 2 + 1 = 3
func(3) = func(2) + func(1) = 1 + 1 = 2
第三步:
func(3) = func(2) + func(1) = 1 + 1 = 2
​
func(n) = func(n - 1) + func(n - 2)
"""
def func(n):print('~~~~',n)if n == 1 or n == 2:return 1else:  # n >= 3return func(n - 1) + func(n - 2)
​
# r1 = func(2)
# print(r1)  # 1
# r1 = func(5)
# print(r1)
# r1 = func(20)
# print(r1)  # 55
# r1 = func(6)
# print(r1)  # 8
​
# b.求1~某个数之间所有整数的和
'''
func(100)--->1~100 = func(99) + 100
func(99) --->1~99 = func(98) + 99
.....
func(n)--->1~n = func(n - 1) + n
'''
​
def func(n):print('~~~~~',n)if n == 1:return 1else:return func(n - 1) + n
​
r2 = func(100)
print(r2)  # 5050
​
# 注意:在实际应用中,不推荐使用递归,相比于循环,递归的效率较低

三、装饰器【掌握】

1.概念

概念:已知一个函数,如果需要给该函数增加新的功能,但是不希望修改原函数,在Python中,这种在代码运行期间动态执行的机制被称为装饰器【Decorator】

装饰器的作用:为已经存在的函数或者类添加额外的功能

装饰器的本质:实际上就是一个闭包,概念:内部函数访问外部函数中的变量【一个已知的函数】

2.基本语法
# 1.闭包
# a
# def outer(n):
#     m = 10
#     def inner():
#         print(m,n)
#     inner()
# outer(20)
​
# b.
# def outer(n):
#     m = 10
#     def inner():
#         print(m,n)
#     return inner   # 切记:需要返回的是函数本身inner,所以不要写成inner()
# f = outer(20)   # 调用的是外部函数
# f()  # 相当于调用的是内部函数inner()
​
​
# 2.装饰器的基本语法
# 注意:自定义函数的过程中,函数名不要出现test,否则会自动调起系统的测试模块
​
# 已知函数:需要被装饰的函数
def a():print('春节快乐')
​
# 书写装饰器:给已知函数增加新的功能
# 基本流程
# a.书写一个闭包,给外部函数设置参数,该参数表示需要被装饰的函数,建议命名:f/fun/func
def outter(func):def inner():# b.为了吻合闭包的概念,在内部函数中访问外部函数中的变量func# func表示一个需要被装饰的函数,所以调用func# 调用原函数print('~~~',func)   # <function a at 0x0000010FB626F040>func()# 增加新的功能print('new~~~~~~')return inner
# c.使用装饰器。将已知的函数作为参数传递给装饰器
# f = inner   func = a
f = outter(a)  # 注意:一个函数作为另一个函数的参数或返回值使用,只需要使用函数名即可
print(f)   # <function outter.<locals>.inner at 0x0000022FD700C4C0>
f()
​
'''
总结:a.outter是装饰器的名称【外部函数的函数名】b.inner是装饰器的核心部分【调用原函数,增加新的功能】c.在inner中,调用原函数和新增功能没有先后顺序,可以根据具体的需求做出调整
'''
3.使用一

使用 @xxx 可以将一个装饰器作用于一个函数上,只需要将@xxx书写在一个函数的前面,则表示xxx装饰器装饰指定的函数@xxx:xxx表示装饰器的名称【外部函数的函数名】注意:如果使用@xxx加载装饰器,则必须装饰器先存在,然后才能使用

def outter(func):print('外部函数~~~~~~start')def inner():# 调用原函数print('inner~~~~~~~~~~')func()# 增加新的功能print('new~~~~~~')
​print('外部函数~~~~~~end')return inner
​
@outter    # 等价于f = outter(a)。调用了外部函数
def a():print('春节快乐')
​
print(a)   # <function outter.<locals>.inner at 0x000001AE54DCC430>
a()    # 等价于 f(),调用了内部函数
​
​
'''
总结:a.使用@xxx装饰某个函数,则该装饰器一定要先存在,然后才能使用b.@xxx本质上表示调用装饰器的外部函数,自动将已知的函数传参给了func,同时自动将返回值inner接出来c.当原函数传参给func之后,此时原函数的函数名就会给重新赋值,赋值为inner,所以a()表示调用的是inner()
'''
4.使用二
# 【面试题】需求:书写一个装饰器,同时装饰多个函数,给多个函数同时增加同一个新的功能
def wrapper(func):print('wrapper~~~~~~~~')def inner(*args,**kwargs):     # 打包print(args,kwargs)func(*args,**kwargs)  # 调用原函数,拆包print('new~~~~~')return inner
​
@wrapper
def a():print('aaa')
​
@wrapper
def b(m,n):print('bbbbb',m,n)
​
@wrapper
def c(num1,num2,num3):print('cccc',num1,num2,num3)
​
a()  # 调用inner
b(3,5)  # 调用inner
c(23,5,7)
​
'''
注意:a.一个装饰器装饰多个函数,则@xxx需要书写多次b.如果一个装饰器装饰多个不同的函数,为了满足不同函数的参数需求,则给装饰器的内部函数设置不定长参数,格式为:*xxx,**xxx
'''
​
# 案例/面试题:书写一个装饰器,可以统计任意一个函数的执行时间
import time
# print(time.time())  # 获取从1970.1.1 00:00:00到当前的时间戳【秒数】
​
def wrapper(func):def get_time(*args,**kwargs):start = time.time()func()end = time.time()return round(end - start,3)   # 保留小数点后3位return get_time
​
@wrapper
def check():for i in range(138232300):pass
​
r = check()
print(f'花费的时间为:{r}')

相关文章:

  • 北京网站建设多少钱?
  • 辽宁网页制作哪家好_网站建设
  • 高端品牌网站建设_汉中网站制作
  • 车机中 Android Audio 音频常见问题分析方法实践小结
  • 基于Vue的兴趣活动推荐APP的设计与实现_kaic
  • 大数据热门技术
  • 【系统架构设计】软件的知识产权保护+标准化概论+应用数学+云计算
  • OceanBase 运维管理工具 OCP 4.x 升级:聚焦高可用、易用性及可观测性
  • Oracle 11gR2打PSU补丁详细教程
  • LVGL学习
  • Android14 待机关机蓝牙自动关闭分析解决
  • 【PowerBi】百日计划,PowerBi矩阵表的使用与表格的自动聚类。
  • H5依赖安装
  • 3-【JavaWeb】Lombok配置及使用方法介绍
  • ubuntu24.04 lts 更新后无法登录, 更新前待机无法恢复.
  • 知识库管理系统在企业数字化转型中的作用
  • C++:STL详解(一)string类的基本介绍与使用方式
  • 【查看谷歌浏览器的个人文件路径】
  • “寒冬”下的金三银四跳槽季来了,帮你客观分析一下局面
  • 【翻译】Mashape是如何管理15000个API和微服务的(三)
  • 2018一半小结一波
  • GDB 调试 Mysql 实战(三)优先队列排序算法中的行记录长度统计是怎么来的(上)...
  • Github访问慢解决办法
  • GitUp, 你不可错过的秀外慧中的git工具
  • Laravel 菜鸟晋级之路
  • MD5加密原理解析及OC版原理实现
  • Median of Two Sorted Arrays
  • 诡异!React stopPropagation失灵
  • 排序算法学习笔记
  • 前端学习笔记之原型——一张图说明`prototype`和`__proto__`的区别
  • 深度学习中的信息论知识详解
  • 听说你叫Java(二)–Servlet请求
  • 一个SAP顾问在美国的这些年
  • ​卜东波研究员:高观点下的少儿计算思维
  • # 利刃出鞘_Tomcat 核心原理解析(八)-- Tomcat 集群
  • ###51单片机学习(2)-----如何通过C语言运用延时函数设计LED流水灯
  • #162 (Div. 2)
  • (2)从源码角度聊聊Jetpack Navigator的工作流程
  • (3)医疗图像处理:MRI磁共振成像-快速采集--(杨正汉)
  • (done) 两个矩阵 “相似” 是什么意思?
  • (react踩过的坑)Antd Select(设置了labelInValue)在FormItem中initialValue的问题
  • (二)斐波那契Fabonacci函数
  • (附源码)node.js知识分享网站 毕业设计 202038
  • (附源码)python房屋租赁管理系统 毕业设计 745613
  • (精确度,召回率,真阳性,假阳性)ACC、敏感性、特异性等 ROC指标
  • (论文阅读23/100)Hierarchical Convolutional Features for Visual Tracking
  • (论文阅读40-45)图像描述1
  • (三)SvelteKit教程:layout 文件
  • (转)可以带来幸福的一本书
  • .NET Compact Framework 多线程环境下的UI异步刷新
  • .NET CORE 2.0发布后没有 VIEWS视图页面文件
  • .net core使用EPPlus设置Excel的页眉和页脚
  • .NET Standard 支持的 .NET Framework 和 .NET Core
  • .net6 当连接用户的shell断掉后,dotnet会自动关闭,达不到长期运行的效果。.NET 进程守护
  • :O)修改linux硬件时间
  • @CacheInvalidate(name = “xxx“, key = “#results.![a+b]“,multi = true)是什么意思
  • [ActionScript][AS3]小小笔记
  • [CR]厚云填补_多云条件下土地覆盖分割的多模态多任务学习