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 关键字来返回值.定义和使用一个最简单的函数例子: >>> ...
随机推荐
- python接口自动化测试(七)-unittest-批量用例管理
我们日常项目中的接口测试案例肯定不止一个,当案例越来越多时我们如何管理这些批量案例?如何保证案例不重复?如果案例非常多(成百上千,甚至更多)时如何保证案例执行的效率?如何做(批量)测试数据的管理?如何 ...
- [Java] 绕过证书验证调 HTTPS 接口时报 “SSLHandshakeException: DHPublicKey does not comply to algorithm constraints”的解决办法
作者: zyl910 一.缘由 最近有在对接一个无证书的HTTPS接口时,总是收到"SSLHandshakeException: DHPublicKey does not comply to ...
- oracle无效索引重建
问题描述: 执行失败!错误信息[Exception message:无效的列索引 解决思路: 分析是表索引,大部分都是表索引失效导致的,只需要花重建表索引即可! 00.查看此表归属账户select * ...
- Cocoapods pod update执行失败报错CocoaPods was not able to update the `master` repo.2019的解决
很久没动pod,最近更新发现: CocoaPods报CocoaPods was not able to update the `master` repo. If this is an unexpect ...
- 【算法】解析IEEE 754 标准
目录结构: contents structure [-] 浮点数的存储过程 次正规数(Denormalized Number) 零(zero) 非数值(NaN) 无穷大(infinity) 除数为0. ...
- mysql存储过程详解 mysql存储过程和函数
第20章:存储程序和函数 目录 20.1. 存储程序和授权表 20.2. 存储程序的语法 20.2.1. CREATE PROCEDURE和CREATE FUNCTION 20.2.2. ALTER ...
- fiddler 对https支持
https://www.cnblogs.com/joshua317/p/8670923.html 测试可行
- 你真的理解Python中MRO算法吗?[转]
[前言] MRO(Method Resolution Order):方法解析顺序.Python语言包含了很多优秀的特性,其中多重继承就是其中之一,但是多重继承会引发很多问题,比如二义性,Python中 ...
- [转] 一个小时学会Git
一个小时学会Git http://www.cnblogs.com/best/p/7474442.html
- final可以修饰类、属性、方法。
当用final修饰类的时候,此类不可被继承,即final类没有子类.这样可以用final保证用户调用时动作的一致性,可以防止子类覆盖情况的发生. 当利用final修饰一个属性(变量)的时候,此 ...