装饰器
【一】函数的四种定义方式
-
无参无返回值的函数
def index(): res = 1 + 1 print(res) index() #2
-
有参无返回值的函数
def index(x): print(x) index(1) #1
-
有参有返回值
def index(x): return x res = index(1) print(res) #1
-
多个参数多个返回值
def add(x, y):
return x + y, x * y
res_one,res_two = add(2,9)
print(res_one)
print(res_two)
res = add(4, 9)
print(len(res))
for i in range(0, len(res)):
res_one = res[i]
print(res_one)
11
18
2
13
36
【二】函数的调用方式
def add(x, y):
return x + y
def multy(a, b,func=None):
if not func:
return a * b
else:
res = func(a, b)
return func(a, b) * a
add(4, 7)
res = add
res(4,7)
print(multy(add(1,9),8))
print(multy(add(1,9),8,func=add))
80
180
【三】函数的参数类型
-
形参 --- 在定义函数时,后面携带的参数名就叫形参
# 如果我们想让其他人就传指定的类型的话,可以做一个弱声明 def add(x: int, y): print(x ) print(y ) add('a',9) # 可变长参数 def add(*args,**kwargs): print(args) # (1, 2, 3, 4, 5) print(kwargs) # {'name': 'dream', 'age': 18} add(1,2,3,4,5,name='dream',age=18) def add(name,age,*,sex,height): print() # 默认参数 -- 不是命名关键字的时候,默认参数必须放在位置参数的后边 def add(name='dream',age,sex,height): print() # 默认参数 -- 如果是命名关键字参数,我的默认参数就可以不区分位置 def add(name,age,*,sex='男',height): print()
-
实参
def add(x,y):
print(x)
# 实参可以是任意类型
# 实参还可以是表达式 add(2+2)
# 实参还可以是函数的返回值
# 实参还可以是函数的地址
# 实参的传参方式
# 按位置传参数
add(8)
# 按关键字传参
add(x=8)
# 注意:关键字传参的时候,位置参数一定要在关键字参数前面
add(7,y=9)
【四】名称空间是什么,有哪些
【1】内建名称空间:随着Python解释器的启动而自动加载的名称空间 : print(max())
【2】全局名称空间(内建 + 我们自己定义的):我们自己在文件中定义的变量名/函数名/类名 ...
【3】局部名称空间:定义在函数内部/定义在类内部加载出来的名称空间
# 内建
print(max([1,2,3]))
# 全局
num = 1
# 局部
def add():
print(num)
add()
局部可以使用全局的变量
全局不能使用局部的变量
【五】作用域是什么,都有哪些
# 【1】内置 -- 内建
# 【2】全局作用域
# 【3】局部作用域
# 【4】嵌套作用域
num = 2
print(num)
def outer():
# 局部修改全局变量需要 在函数内容 用 global 声明全局变量
global num
print(num)
num += 1
print(num)
outer()
print(num)
num = 2
def outer():
# 局部修改全局变量需要 在函数内容 用 global 声明全局变量
global num
num_inner = 99
def inner():
nonlocal num_inner
num_inner += 99
inner()
print(num_inner)
num += 1
outer()
print(num)
# *什么是闭包函数
# 闭包函数就是内嵌函数对外部函数作用域有引用的函数
num = 2
def outer():
global num
num_inner = 99
def inner():
nonlocal num_inner
num_inner += 99
print(num_inner)
num += 1
return inner
inner = outer()
print(num)
inner()
【一】什么是装饰器
装饰
代指为被装饰对象添加新的功能,器
代指器具/工具,装饰器与被装饰的对象均可以是任意可调用对象。- 概括地讲,装饰器的作用就是在不修改被装饰对象源代码和调用方式的前提下为被装饰对象添加额外的功能。
- 装饰器经常用于有切面需求的场景
- 插入日志、性能测试、事务处理、缓存、权限校验等应用场景
- 装饰器是解决这类问题的绝佳设计
- 有了装饰器,就可以抽离出大量与函数功能本身无关的雷同代码并继续重用。
【二】装饰器的作用
- 软件的设计应该遵循开放封闭原则,即对扩展是开放的,而对修改是封闭的。
- 对扩展开放,意味着有新的需求或变化时,可以对现有代码进行扩展,以适应新的情况。
- 对修改封闭,意味着对象一旦设计完成,就可以独立完成其工作,而不要对其进行修改。
- 软件包含的所有功能的源代码以及调用方式,都应该避免修改,否则一旦改错,则极有可能产生连锁反应,最终导致程序崩溃
- 而对于上线后的软件,新需求或者变化又层出不穷,我们必须为程序提供扩展的可能性,这就用到了装饰器。
【三】装饰器的分类
- 函数装饰器分为:无参装饰器和有参装饰两种
- 二者的实现原理一样,都是’函数嵌套+闭包+函数对象’的组合使用的产物。
【四】装饰器
import time
def login():
time.sleep(1)
def register():
time.sleep(1)
start_time = time.time()
login()
print(f'总耗时 {time.time() - start_time} s')
start_time = time.time()
register()
print(f'总耗时 {time.time() - start_time} s')
login_user_dict = {'username': 'dream', 'is_admin': True}
user_data_dict = {'dream': {'password': 123, 'role': 'admin'},
'hope': {'password': 456, 'role': 'normal'}}
def login(username, password):
if password == user_data_dict[username].get('password'):
print(f"登陆成功")
login_user_dict['username'] = username
if user_data_dict[username].get('role') == 'admin':
login_user_dict['is_admin'] = True
else:
login_user_dict['is_admin'] = False
def check_admin(func):
def inner():
if login_user_dict['username'] and login_user_dict['is_admin']:
res = func()
print(f'check_admin 内部的 res {res}')
return res
else:
return False, '重新登录'
return inner
# @check_admin
def get_money():
return True, f'取了一万块'
# print(get_money())
get_money = check_admin(func=get_money)
get_money()
print(get_money())
def add():
return 1 + 1
num = 2
def outer(func):
def inner():
if num == 3:
res = func()
print(func)
return res
else:
return False
return inner
add = outer(func=add)
print(add())
【五】无参装饰器模板
# 装饰器模板
def outer():
def inner():
...
return inner
# 传参数
def add():
return 1
def outer(func):
def inner():
res = func()
return res
return inner
add = outer(func=add)
add()
def add():
return 1
def outer(func):
def inner():
'''这里写调用 func 函数之前的逻辑'''
res = func()
'''这里写调用 func 函数之后的逻辑'''
return res
return inner
add = outer(func=add)
add()
login_user_dict = {'username': 'dream', 'is_admin': False}
def outer(func):
def inner():
'''这里写调用 func 函数之前的逻辑 :必须是登陆过后并且是管理员才能执行 add 函数'''
if login_user_dict['username'] and login_user_dict['is_admin']:
res = func()
'''这里写调用 func 函数之后的逻辑'''
return res
else:
return False,'必须是管理员并且登陆了'
return inner
@outer # --- > add = outer(add)
def add():
return True,f'add函数被执行了'
print(add())
add = outer(func=add)
print(add())
# 装饰器模板
def outer(func):
def inner():
'''这里写调用 func 函数之前的逻辑'''
res = func()
'''这里写调用 func 函数之后的逻辑'''
return res
return inner
【六】装饰器练习
# 看电影
# 用户信息字典 --- 定义用户名 和 年龄
# 大于 18 岁 看电影
# 小于 18 岁 18禁
# 取钱 ---> 登录(装饰器验证登录)
# 看电影 ==》 验证年龄(装饰器验证年龄)
user_data_dict = {'dream': 19, 'hope': 17}
user={'zhangs':17,'lis':19}
def watch(func):
def inner(name):
if user[name]>=18:
res=func()
return res
else:
return '18禁'
return inner
def see():
return '看电影'
see=watch(see)
print(see('zhangs'))
print(see('lis'))
def outer(func):
def inner(*args,**kwargs):
if user_data_dict[args[0]] >= 18:
res = func(args[0])
return res
else:
return False, f'18禁'
return inner
def watch(name):
return True, f'{name} :>>> 看电影'
watch = outer(watch)
print(watch('dream'))
# 带参数装饰器模板
def outer(func):
def inner(*args,**kwargs):
'''这里写调用 func 函数之前的逻辑 直接校验年龄'''
res = func(*args,**kwargs)
'''这里写调用 func 函数之后的逻辑'''
return res
return inner
@outer
def add(*args,**kwargs):
print(args)
print(kwargs)
add(888,x=999)