day12 十二、开放封闭、装饰器
一、nonlocal关键词
1、作用:将local和enclosing(e中的名字需要提前定义)中的名字统一
2、应用场景:如果想在被嵌套的函数中修改外部函数变量(名字)的值
3、案例
def outer():
num = 0
print(num) # 结果为 0
def inner(): # 如果想在被嵌套的函数中修改外部函数变量(名字)的值
nonlocal num # 将L与E(E中的名字需要提前定义)的名字统一
num = 100
print(num) # 结果为 100
inner()
print(num) # 结果为 100
outer()
num =100
def fn():
global num
num = 10
def fn2():
global num
num = 20
fn2()
fn()
print(num)
二、开放封闭原则
1、定义:不能修改源代码,不能更改调用方式,但可以对外提供增加新功能的特性
2、开放:修改了源代码,没有更改调用方式,对外调用方式还是原来的,但功能有所增加,不能更改被装饰对象(函数)的调用方式,且达到了增加功能的效果
def fn():
print('fn run1')
print('fn run')
print('fn run3')
fn()
3、封闭:没有修改源代码,但更改了调用方式 。
不能修改被被装饰对象(函数)的源代码
def fn():
print('fn run')
fn()
def wrap(fn):
print('fn run1')
fn()
print('fn run3')
fn()
wrap(fn)
三、装饰器
1、装饰器:闭包的一个应用场景。为一个函数添加新功能的工具
def vase():
print('插花')
vase() # 结果为 插花 # 增加一个绘画观赏功能:不满足封闭开放原则,修改了源代码
def vase():
print('插花')
print('绘画观赏')
vase()
# 结果为
# 插花
# 绘画观赏 # 增加一个绘画观赏功能,不满足开放封闭原则,更改了调用方式
def vase():
print('插花')
vase()
def wrap(vase):
vase()
print('绘画观赏')
wrap(vase)
def vase():
print('插花') def wrap(vase):
def fn():
print('绘画观赏')
return fn
vase = wrap(vase)
vase()
def vase():
print('插花') # 下方的函数嵌套结构就是装饰器*****
def wrap(x): #x=vase
def fn():
x() # 原有的vase
print('绘画:进行观赏')
return fn # 拓展功能后的vase
vase = wrap(vase) # 将拓展功能后的功能函数重新赋值给vase
vase() # 功能拓展了,且调用方式不变
2、装饰器简化语法
def outer(fn):
def inner():
fn()
print('绘画观赏')
return inner
def wrap(fn):
def inner():
fn()
print('摆放功能')
return inner
# 语法糖|笑笑语法
@wrap # 总结:一个函数可以被任意一个装饰器装饰,也可以被任意几个装饰器装饰
@outer # 装饰的顺序会影响新增功能的执行顺序 def vase():
print('插花')
vase()
# 结果为
# 插花
# 绘画观赏
# 摆放功能
四、有参有反的函数被装饰
案例 # 增加一个账号处理功能: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)
return inner # 登录功能
@check_usr # login = check_usr(login) = inner
@check_pwd
def login(usr, pwd):
if usr == 'abc' and pwd =='123qwe':
print('登录成功')
return True
print('登录失败')
return False res = login('abc', '123qwe') # inner
print(res)
五、登录认证案例
is_login = False # 登录状态 def login():
usr = input('usr: ')
if not (len(usr) >= 3 and usr.isalpha()):
print('账号验证失败')
return False
pwd = input('pwd: ')
if usr == 'abc' and pwd =='123qwe':
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
return inner # 查看个人主页功能
@check_login
def home():
print('个人主页') # 销售功能
@check_login
def sell():
print('可以销售') home()
五、案例
1、写出完整的装饰器(不用考虑带参装饰器,就是普通装饰器)语法
def wrapper(func):
def inner(*args, **kwargs):
pass
result = func(*args, **kwargs)
pass
return result
return inner
2、有一个计算两个数和的方法,为其添加一个确保两个参数都是int或float类型的装饰器,保证运算不会抛异常
def check_num(func):
def inner(n1, n2):
b1 = isinstance(n1, int) or isinstance(n1, float)
b2 = isinstance(n2, int) or isinstance(n2, float)
if not (b1 and b2):
print('不能求和')
return # 结束掉,不让其进入计算功能
return func(n1, n2)
return inner @check_num
def add(n1, n2):
return n1 + n2 print(add(1, ''))
3、有一个一次性录入人名并返回人名的方法(人名只考虑存英文),为其添加一个装饰器,使得处理后人名首字母一定大写
def upper_name(func):
def inner():
result = func()
return result.title() # Owen
return inner @upper_name
def get_name():
name = input('name: ') # owen
return name print(get_name())
day12 十二、开放封闭、装饰器的更多相关文章
- 十二、Decorator 装饰器模式
设计: 代码清单: Display public abstract class Display { public abstract int getColumns(); public abstract ...
- 十. Python基础(10)--装饰器
十. Python基础(10)--装饰器 1 ● 装饰器 A decorator is a function that take a function as an argument and retur ...
- Python小白学习之路(二十四)—【装饰器】
装饰器 一.装饰器的本质 装饰器的本质就是函数,功能就是为其他函数添加附加功能. 利用装饰器给其他函数添加附加功能时的原则: 1.不能修改被修饰函数的源代码 2.不能修改被修饰函数的调用 ...
- Python小白学习之路(二十五)—【装饰器的应用】
通过一个任务来加深对装饰器的理解和应用 回顾:装饰器的框架 def timmer(func): def wrapper(): func() return wrapper 任务:给以下正在运行的程序加一 ...
- python学习 day12 (3月18日)----(装饰器内置函数)
读时间函数: # import time # def func(): # start_time = time.time() # 代码运行之前的时间 # print('这是一个func函数') # ti ...
- python 二——函数、装饰器、生成器、面向对象编程(初级)
本节内容 1.函数 2.装饰器 3.生成器 4.类 一.函数 函数式:将某功能代码封装到函数中,日后便无需重复编写,仅调用函数即可 面向对象:对函数进行分类和封装,让开发“更快更好更强...” 函数式 ...
- python入门(十五):装饰器
1.装饰器(decorator):设计模式 作用:给不同的函数和方法,增加不同的公用的功能. @classmethod,@staticmethod等均是装饰器 定义一个装饰函数,函数必须返回一个闭包函 ...
- python二 总结--函数-- 装饰器
装饰器是什么? 有什么用? 为什么要用? 真的有用吗? 1.装饰器: 装饰器: 定义:本质是函数,(装饰其他函数)就是为其他函数添加附加功能. 原则:1.不能修改被装饰的函数的源代码 ...
- (二)Python 装饰器
1. 函数 在 Python 中,使用关键字 def 和一个函数名以及一个可选的参数列表来定义函数.函数使用 return 关键字来返回值.定义和使用一个最简单的函数例子: >>> ...
随机推荐
- Foxmail中配置O365邮箱和Hotmail邮箱
一.简述 平时我们经常使用第三方的邮箱工具来管理邮箱.可能性能比Outlook好很多,比如Foxmail,而且也能和Skype会议关联的很好.本文就讲如何在Outlook中关联Office365邮箱和 ...
- 使用Træfɪk(traefik)来加速Qt在线更新
简述 在使用Qt的MaintenanceTool程序进行在线更新的时候遇到一个问题,就是访问download.qt.io实在太慢了,老是失败.所以想使用国内的镜像站来进行更新. 使用Qt的镜像站方法也 ...
- manjaro折腾手记
以前装过Arch,有点折腾,写了个hello world就卸载了.没用过AUR,甚至也没去了解. 听说manjaro继承Arch,几乎开箱即用,对硬件支持非常好,源里面的软件更新非常快.但是没有装中文 ...
- C#之值类型和引用类型
本文意在巩固基础知识,并不是对其进行深入剖析,还望理解.本文是对此项知识的整理文,有些内容来源于网络,其他为博主原创,所以难免会有一些小得瑕疵,敬请谅解.所有示例均是博主测试过的,如有转载请标明出处, ...
- 评分模型的检验方法和标准&信用评分及实现
评分模型的检验方法和标准通常有:K-S指标.交换曲线.AR值.Gini数等.例如,K-S指标是用来衡量验证结果是否优于期望值,具体标准为:如果K-S大于40%,模型具有较好的预测功能,发展的模型具有成 ...
- mycat偶尔会出现JVM报错double free or corruption并崩溃退出
mycat偶尔会出现JVM报错double free or corruption并崩溃退出 没有复杂的sql,也没有大量的io INFO | jvm | // :: | *** Error in `j ...
- [转]ThreadLocal使用
引言 ThreadLocal的官方API解释为: “该类提供了线程局部 (thread-local) 变量.这些变量不同于它们的普通对应物,因为访问某个变量(通过其 get 或 set 方法)的每个线 ...
- 线程封装组件(BackgroundWorker)和线程(Thread)
BackgroundWorker是微软的在.net Framwork中添加的一个组件,主要对线程的访问提供了一种安全的方式.简单的说就是对Thread的一次封装. BackgroundWorker位于 ...
- ie11开发者模式打开空白
Internet选项——高级——取消 禁用脚本调试(Internet explorpr)
- python之字符串操作方法
定义及特性: 以引号(单引号,双引号,三引号)包围且不能修改 a= ' \t aBcdE fgFijDlmNopq rSt uTwxy z 123 !@# \t ' 一.判断字符串,返回bool值:F ...