1、作用:将L与E(E中的名字需要提前定义)的名字统一
2、应用场景:如果想在被嵌套的函数中修改外部函数变量(名字)的值
def outer():
num=10
print(num) # 输出结果为10
def inner():
nonlocal num
num=20
print(num) #输出级结果为20
inner()
print(num) # 输出结果为20
def outer():
num=0 # 必要写 是用于L与E的名字统一
def inner():
# 如果想被嵌套的函数中修改外部函数变量(名字)的值
nonlocal num # 将L与E(E中的名字需提前定义好)的名字统一
num=10
print(num) # 输出结果为10
inner()
print(num ) # 定义了nonlocal就是局部统一,输出结果为10
outer()
# print(num)# 属于全局,不能看到其值
1、原则: 不能修改被装饰对象(函数)的源代码——封闭
不能更改被修饰对象(函数)的调用方式,且能达到增加功能的效果——开放
1.0版本
def fn():
print('fn run ')
fn()
版本2.0
def fn2():
print('fn run 0')
print('fn run1')
print('fn run2')
修改了源代码,没有更改调用方式,对外调用方式还是原来的,
def fn():
print('fn run0')
print('fn run ')
print('fn run2')
更改了调用方式,没有修改原功能代码块
def wrap(fn):
print('fn run0')
fn()
print('fn run2')
wrap(fn)
1、定义:就是闭包(闭包的一个应用场景)
把要装饰的函数作为外部函数的参数通过闭包操作返回一个替代版函数1
2、优点:丰富了原有函数的功能
提高了程序的可拓展性
把要被装饰的函数作为外层函数的参数通过闭包操作后返回一个替代版函数
被装饰的函数:fn
外层函数:outer(func)、outer(fn)==》func=fn
替代版函数;return inner:原有功能加新功能
def fn():
print('原有功能')
# 装饰器
def outer(tag):
def inner():
tag()
print('新增功能')
return inner
fn=outer(fn)
fn()
案例 花瓶
def vase():
print('插花')
vase()
增加一个绘画后观赏功能
def wrap(fn):
vase()
print('插花')
print('绘画:进行观赏')
wrap(vase)
虽然满足了开放封闭原则,但出现了函数调用死循环
def fn():
vase()
print('绘画:进行观赏')
vase=fn()
vase()
了解:满足开放fengbiyuanze,且可以达到装饰器的作用:拓展功能
tag=vase # 暴露在全局:
def fn():
tag()
print('绘画:进行观赏')
vase=fn
vase()
满足开放封闭原则(完美方法)
方式一
def wrap (tag):
tag=vase
def fn():
tag()
print('绘画:进行观赏')
return fn # 拓展功能后的vase
vase =wrap() # 相当于vase=fn
vase()
方式二、这个函数嵌套结构就是装饰器
def wrap (tag):
def fn():
tag() # 指原有的vase
print('绘画:进行观赏')
return fn # 拓展功能后的vase
vase =wrap(vase) # 将拓展功能后的函数重新赋值给vase
vase() # 功能拓展了,且调用方式不变
ef outer(f):
def inner():
f()
print("新增功能1")
return inner
def wrap(f):
def inner():
f()
print("新增功能2")
return inner
@wrap # 被装饰的顺序决定了新增功能的执行顺序
@outer # <==> fn = outer(fn): inner
def fn():
print("原有功能")
案例:
def outer (fn):
def inner():
fn()
print('绘画:进行观赏')
return inner
def wrse (fn):
def inner():
fn()
print('摆放功能')
return inner
@语法糖|笑笑语法
@wrse
@outer #等于这个功能<==>vase =outer(vase)
def vase():
print('插花')
vase()
总结:一个函数可以被任意一个相关装饰器装饰,也可以被任意几个装饰器装饰
注:装饰的顺序会影响新增功能的执行顺序
def check_usr(fn):# fn,login,inner:不同状态下的login,所以参数是统一的
def inner(usr,pwd):
# 在原功能上添加新功能
if not(len(usr)>=3and usr.isalpha()):
print('账号验证失败')
return False
# 原有功能
result=fn(usr,pwd)
# 在原功能下添加新功能
#。。。。。()没有添加则用句号省略了
return result
return inner
@check_usr
def login(usr,pwd):
if usr=='abc'and pwd=='123abc':
print('登录成功')
return True
print('登录失败')
return False
总结:1、login有参数,所以inner与fn都有相同参数
2、login有返回值,所以inner与fn都有返回值
inner(usr, pwd):
res = fn(usr, pwd) # 原login的返回值
return res
login = check_usr(login) = inner
res = login('abc', '123qwe') # inner的返回值
案例:
增加一个账号处理功能:3位以上英文字符或汉字
def check_usr(fn):
def inner(usr,pwd):
if not (len(usr)>=3 and usr.isalpha()):
print('账号验证失败')
return False
result=fn(usr,pwd) #login
return result
return inner
增加一个密码处理功能:6位以上英文和数字
def check_pwd(fn):
def inner(usr,pwd):
if not (len(pwd)>=6 and pwd.isalnum()):
print('密码验证失败')
return False
return fn(usr,pwd) #result=fn(usr,pwd) return result
return inner
登录功能
@check_usr # login=check_usr(login)=inner
def login(usr,pwd):
if usr=='abc' and pwd=='123abc':
print('登录成功')
print('登录失败')
return False
res=login('abc','123abc') # inner 用户名和密码正确输出验证成功
print(res)
# 装饰器的最终写法
def wrap (fn):
def inner(*args,**kwargs):
print('前增功能')
result =fn(*args,**kwargs)
print('后增功能')
return result
return inner
@wrap
def fn1():
print('fn1的原有功能')
@wrap
def fn2(a,b): # 有参数无值
print('fn2的原有功能')
@wrap
def fn3():# 有返回值无参数
print('fn2的原有功能')
return True
@wrap
def fn4(a,*,c): #有参数有返回值
print('fn2的原有功能')
return True
fn1()
fn2(10,20)
fn3()
fn4(10,c=20)
案例:
增加一个账号处理功能:3位及以上英文字符或汉字
def check_usr(fn):
def inner(usr,pwd):
if not(len(usr)>=3 and usr.isalpha()):
print('账号验证失败')
return False
result=fn(usr,pwd) #login
return result
return inner
登录功能
@check_usr
def login(usr,pwd):
if usr=='abc'and pwd=='123abc':
print('登录成功')
return True
print('登录失败')
return False
res=login('abc','123abc') #inner 账号密码正确打印成功
print(res)
带参装饰器
def outer(input_color):
def wrap(fn):
if input_color=='red':
info='\033[36;41m new action\33[0m'
else:
info='yellow:new action'
def inner(*args,**kwargs):
pass
result=fn(*args,**kwargs)
print(info)
return result
return inner
return wrap #outer(color)=>>wrap
color=input('color:')
def func():
print('func run')
func()
is_login=False #登录状态
def login():
usr=input('usr:')
if not(len(usr)>=3 and usr.isalpha()):
print('账号验证失败')
return False
pwd=input('ped:')
if usr=='abc'and pwd=='123abc':
print('登录成功')
is_login=True
else:
print('登录失败')
is_login=False
完成一个登录状态校验的装饰器
def check_login(fn):
def inner(*args,**kwargs):
# 查看个人主页或销售功能前:如果没有登录需要先登录,繁殖可以进入其功能
if is_login!=True:
print('你未登录')
login()
# 查看个人主页或销售
result=fn(*args,**kwargs)
return result
查看个人主页功能
@check_login
def home():
print('个人主页')
销售功能
@check_login
def sell():
print('可以销售')
home()