Python——day12 nonlcoal关键字、装饰器(开放封闭原则、函数被装饰、最终写法)
一、nonlocal关键字
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= # 必要写 是用于L与E的名字统一
def inner():
# 如果想被嵌套的函数中修改外部函数变量(名字)的值
nonlocal num # 将L与E(E中的名字需提前定义好)的名字统一
num=
print(num) # 输出结果为10
inner()
print(num ) # 定义了nonlocal就是局部统一,输出结果为10
outer()
# print(num)# 属于全局,不能看到其值
二、开放封闭原则
1、原则: 不能修改被装饰对象(函数)的源代码——封闭
不能更改被修饰对象(函数)的调用方式,且能达到增加功能的效果——开放
.0版本
def fn():
print('fn run ')
fn() 版本2.
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()
Python——day12 nonlcoal关键字、装饰器(开放封闭原则、函数被装饰、最终写法)的更多相关文章
- 【Python入门学习】闭包&装饰器&开放封闭原则
1. 介绍闭包 闭包:如果在一个内部函数里,对在外部作用域的变量(不是全局作用域)进行引用,那边内部函数被称为闭包(closure) 例如:如果在一个内部函数里:func2()就是内部函数, 对在外部 ...
- python 装饰器 对类和函数的装饰
#装饰器:对类或者函数进行功能的扩展 很多需要缩进的没有进行缩进'''#第一步:基本函数def laxi(): print('拉屎')#调用函数laxi()laxi() print('======= ...
- Day 12 开放封闭原则,装饰器初识
nonlocal关键字 # 作用:将 L 与 E(E中的名字需要提前定义) 的名字统一# 应用场景:如果想在被嵌套的函数中修改外部函数变量(名字)的值# 案例:def outer(): n ...
- 装饰器和"开放-封闭"原则
装饰器和"开放-封闭"原则 "开放-封闭"原则 软件开发中的"开放-封闭"原则,它规定已经实现的功能代码不应该被修改,但可以被扩展,即: 封 ...
- 【Python 函数对象 命名空间与作用域 闭包函数 装饰器 迭代器 内置函数】
一.函数对象 函数(Function)作为程序语言中不可或缺的一部分,但函数作为第一类对象(First-Class Object)却是 Python 函数的一大特性. 那到底什么是第一类对象(Firs ...
- Python装饰器、内置函数之金兰契友
装饰器:装饰器的实质就是一个闭包,而闭包又是嵌套函数的一种.所以也可以理解装饰器是一种特殊的函数.因为程序一般都遵守开放封闭原则,软件在设计初期不可能把所有情况都想到,所以一般软件都支持功能上的扩展, ...
- Python学习之路基础篇--11-12Python基础,函数的装饰器
对于装饰器来说,就是在不改变函数的调用的情况下,对函数的前后增加了些许功能,这完全符合函数的 开放封闭 原则.装饰器的本质 其实就是一个闭包函数. 这是一个装饰器的步骤图 ret = func(*ar ...
- python函数知识七 闭包、装饰器一(入门)、装饰器二(进阶)
21.闭包 闭包:在嵌套函数内,使用非全局变量(且不使用本层变量) 闭包的作用:1.保证数据的安全性(纯洁度).2.装饰器使用 .__closure__判断是否是闭包 def func(): a = ...
- python 装饰器(四):装饰器基础(三)叠放装饰器,参数化装饰器
叠放装饰器 示例 7-19 演示了叠放装饰器的方式:@lru_cache 应用到 @clock 装饰fibonacci 得到的结果上.在示例 7-21 中,模块中最后一个函数应用了两个 @htmliz ...
随机推荐
- SpringBoot热部署
SpringBoot的热部署方式分为两种 1.SpringLoader 方式一:以maven插件方式使用SpringLoader <!-- Springloader插件 --> 1.1 ...
- DAY1 VS2017&CUDA10.01环境搭建
Visual Studio工程配置情况: VC++目录配置: C:\ProgramData\NVIDIA Corporation\CUDA Samples\v10.\common\lib\x64 C: ...
- python: 列表的方法
操作 函数 使用方法 备注 索引 index in: example.index(‘creative’) --- 1 in:example[1,] --- [’creative’, [’京东’,996 ...
- BZOJ1431 : MLand
考虑任意一棵生成树,它的代价是一个一次函数. 因此所有生成树的最小值随着时间变化呈现出的是一个上凸壳. 三分查找最大值即可. 时间复杂度$O(m\log m\log w)$. #include< ...
- 在dcef3当中执行js代码并获得返回值
1.如何在dcef3当中执行js代码 procedure TForm1.btnWriteZMClick(Sender: TObject);var js: string;begin js := 'd ...
- [zt+总结]wpf 应用权限问题
一.Inno Setup打包添加和去除管理员权限 转载:https://www.cnblogs.com/walker-lc/articles/3470679.html 添加管理员权限 1.在[Setu ...
- phantomjs api文档
phantomjs实现了一个无界面的webkit浏览器.虽然没有界面,但dom渲染.js运行.网络访问.canvas/svg绘制等功能都很完备,在页面抓取.页面输出.自动化测试等方面有广泛的应用. 详 ...
- Linux神奇命令之---tar
在生产中会常常用到压缩,解压缩,打包,解包等,这时候tar这个万能的小老弟就是是必不可少的了.linux中最流行的tar是麻雀虽小,五脏俱全,功能强大. tar命令可以为linux的文件和目录创建档案 ...
- laravel 目录权限
chown -R www:www /data/wwwroot #变更目录所有者并向下传递 find /data/wwwroot/ -type d -exec chmod 755 {} \; # ...
- Bandwagon的配置记录(一) —— kexue上网
写在前面 这是kexue上网的一种方法. 看文章前,先拉最底下,看一遍“写在最后”. 租个服务器 我租了个洛杉矶的服务器,系统是ubuntu16.04 x86_64 进入KiwiVM Control ...