一、nonlocal关键词

1、作用:将local和enclosing(e中的名字需要提前定义)中的名字统一

2、应用场景:如果想在被嵌套的函数中修改外部函数变量(名字)的值

3、案例

  1. def outer():
  2. num = 0
  3. print(num) # 结果为 0
  4. def inner(): # 如果想在被嵌套的函数中修改外部函数变量(名字)的值
  5. nonlocal num # 将L与E(E中的名字需要提前定义)的名字统一
  6. num = 100
  7. print(num) # 结果为 100
  8. inner()
  9. print(num) # 结果为 100
  10. outer()
  1. num =100
  2. def fn():
  3. global num
  4. num = 10
  5. def fn2():
  6. global num
  7. num = 20
  8. fn2()
  9. fn()
  10. print(num)

二、开放封闭原则

1、定义:不能修改源代码,不能更改调用方式,但可以对外提供增加新功能的特性

2、开放:修改了源代码,没有更改调用方式,对外调用方式还是原来的,但功能有所增加,不能更改被装饰对象(函数)的调用方式,且达到了增加功能的效果

  1. def fn():
  2. print('fn run1')
  3. print('fn run')
  4. print('fn run3')
  5. fn()

3、封闭:没有修改源代码,但更改了调用方式 。

不能修改被被装饰对象(函数)的源代码

  1. def fn():
  2. print('fn run')
  3. fn()
  4. def wrap(fn):
  5. print('fn run1')
  6. fn()
  7. print('fn run3')
  8. fn()
  9. wrap(fn)

三、装饰器

1、装饰器:闭包的一个应用场景。为一个函数添加新功能的工具

  1. def vase():
  2. print('插花')
  3. vase() # 结果为 插花
  4.  
  5. # 增加一个绘画观赏功能:不满足封闭开放原则,修改了源代码
  6. def vase():
  7. print('插花')
  8. print('绘画观赏')
  9. vase()
  10. # 结果为
  11. # 插花
  12. # 绘画观赏
  13.  
  14. # 增加一个绘画观赏功能,不满足开放封闭原则,更改了调用方式
  15. def vase():
  16. print('插花')
  17. vase()
  18. def wrap(vase):
  19. vase()
  20. print('绘画观赏')
  21. wrap(vase)
  1. def vase():
  2. print('插花')
  3.  
  4. def wrap(vase):
  5. def fn():
  6. print('绘画观赏')
  7. return fn
  8. vase = wrap(vase)
  9. vase()
  1. def vase():
  2. print('插花')
  3.  
  4. # 下方的函数嵌套结构就是装饰器*****
  5. def wrap(x): #x=vase
  6. def fn():
  7. x() # 原有的vase
  8. print('绘画:进行观赏')
  9. return fn # 拓展功能后的vase
  10. vase = wrap(vase) # 将拓展功能后的功能函数重新赋值给vase
  11. vase() # 功能拓展了,且调用方式不变

2、装饰器简化语法

  1. def outer(fn):
  2. def inner():
  3. fn()
  4. print('绘画观赏')
  5. return inner
  6. def wrap(fn):
  7. def inner():
  8. fn()
  9. print('摆放功能')
  10. return inner
  11. # 语法糖|笑笑语法
  12. @wrap # 总结:一个函数可以被任意一个装饰器装饰,也可以被任意几个装饰器装饰
  13. @outer # 装饰的顺序会影响新增功能的执行顺序
  14.  
  15. def vase():
  16. print('插花')
  17. vase()
  18. # 结果为
  19. # 插花
  20. # 绘画观赏
  21. # 摆放功能

四、有参有反的函数被装饰

  1. 案例
  2.  
  3. # 增加一个账号处理功能:3位及以上英文字符或汉字
  4. def check_usr(fn):
  5. def inner(usr, pwd):
  6. if not (len(usr) >= 3 and usr.isalpha()):
  7. print('账号验证失败')
  8. return False
  9. result = fn(usr, pwd) # login
  10. return result
  11. return inner
  12.  
  13. # 增加一个密码处理功能:6位及以上英文和数字
  14. def check_pwd(fn):
  15. def inner(usr, pwd):
  16. if not (len(pwd) >= 6 and pwd.isalnum()):
  17. print('密码验证失败')
  18. return False
  19. return fn(usr, pwd)
  20. return inner
  21.  
  22. # 登录功能
  23. @check_usr # login = check_usr(login) = inner
  24. @check_pwd
  25. def login(usr, pwd):
  26. if usr == 'abc' and pwd =='123qwe':
  27. print('登录成功')
  28. return True
  29. print('登录失败')
  30. return False
  31.  
  32. res = login('abc', '123qwe') # inner
  33. print(res)

五、登录认证案例

  1. is_login = False # 登录状态
  2.  
  3. def login():
  4. usr = input('usr: ')
  5. if not (len(usr) >= 3 and usr.isalpha()):
  6. print('账号验证失败')
  7. return False
  8. pwd = input('pwd: ')
  9. if usr == 'abc' and pwd =='123qwe':
  10. print('登录成功')
  11. is_login = True
  12. else:
  13. print('登录失败')
  14. is_login = False
  15.  
  16. # 完成一个登录状态校验的装饰器
  17. def check_login(fn):
  18. def inner(*args, **kwargs):
  19. # 查看个人主页或销售功能前:如果没有登录先登录,反之可以进入其功能
  20. if is_login != True:
  21. print('你未登录')
  22. login()
  23. # 查看个人主页或销售
  24. result = fn(*args, **kwargs)
  25. return result
  26. return inner
  27.  
  28. # 查看个人主页功能
  29. @check_login
  30. def home():
  31. print('个人主页')
  32.  
  33. # 销售功能
  34. @check_login
  35. def sell():
  36. print('可以销售')
  37.  
  38. home()

五、案例

1、写出完整的装饰器(不用考虑带参装饰器,就是普通装饰器)语法

  1. def wrapper(func):
  2. def inner(*args, **kwargs):
  3. pass
  4. result = func(*args, **kwargs)
  5. pass
  6. return result
  7. return inner

2、有一个计算两个数和的方法,为其添加一个确保两个参数都是int或float类型的装饰器,保证运算不会抛异常

  1. def check_num(func):
  2. def inner(n1, n2):
  3. b1 = isinstance(n1, int) or isinstance(n1, float)
  4. b2 = isinstance(n2, int) or isinstance(n2, float)
  5. if not (b1 and b2):
  6. print('不能求和')
  7. return # 结束掉,不让其进入计算功能
  8. return func(n1, n2)
  9. return inner
  10.  
  11. @check_num
  12. def add(n1, n2):
  13. return n1 + n2
  14.  
  15. print(add(1, ''))

3、有一个一次性录入人名并返回人名的方法(人名只考虑存英文),为其添加一个装饰器,使得处理后人名首字母一定大写

  1. def upper_name(func):
  2. def inner():
  3. result = func()
  4. return result.title() # Owen
  5. return inner
  6.  
  7. @upper_name
  8. def get_name():
  9. name = input('name: ') # owen
  10. return name
  11.  
  12. print(get_name())

day12 十二、开放封闭、装饰器的更多相关文章

  1. 十二、Decorator 装饰器模式

    设计: 代码清单: Display public abstract class Display { public abstract int getColumns(); public abstract ...

  2. 十. Python基础(10)--装饰器

    十. Python基础(10)--装饰器 1 ● 装饰器 A decorator is a function that take a function as an argument and retur ...

  3. Python小白学习之路(二十四)—【装饰器】

    装饰器 一.装饰器的本质 装饰器的本质就是函数,功能就是为其他函数添加附加功能. 利用装饰器给其他函数添加附加功能时的原则: 1.不能修改被修饰函数的源代码        2.不能修改被修饰函数的调用 ...

  4. Python小白学习之路(二十五)—【装饰器的应用】

    通过一个任务来加深对装饰器的理解和应用 回顾:装饰器的框架 def timmer(func): def wrapper(): func() return wrapper 任务:给以下正在运行的程序加一 ...

  5. python学习 day12 (3月18日)----(装饰器内置函数)

    读时间函数: # import time # def func(): # start_time = time.time() # 代码运行之前的时间 # print('这是一个func函数') # ti ...

  6. python 二——函数、装饰器、生成器、面向对象编程(初级)

    本节内容 1.函数 2.装饰器 3.生成器 4.类 一.函数 函数式:将某功能代码封装到函数中,日后便无需重复编写,仅调用函数即可 面向对象:对函数进行分类和封装,让开发“更快更好更强...” 函数式 ...

  7. python入门(十五):装饰器

    1.装饰器(decorator):设计模式 作用:给不同的函数和方法,增加不同的公用的功能. @classmethod,@staticmethod等均是装饰器 定义一个装饰函数,函数必须返回一个闭包函 ...

  8. python二 总结--函数-- 装饰器

    装饰器是什么? 有什么用? 为什么要用? 真的有用吗? 1.装饰器: 装饰器: 定义:本质是函数,(装饰其他函数)就是为其他函数添加附加功能. 原则:1.不能修改被装饰的函数的源代码          ...

  9. (二)Python 装饰器

    1. 函数 在 Python 中,使用关键字 def 和一个函数名以及一个可选的参数列表来定义函数.函数使用 return 关键字来返回值.定义和使用一个最简单的函数例子: >>> ...

随机推荐

  1. Javascript 函数声明、函数表达式与匿名函数自执行表达式

    函数表达式(Function Expression)注:将函数定义为表达式语句(通常是变量赋值)的一部分 //func() 错误 var func = function () { } //func() ...

  2. 开发app前需要提前准备的资料

    需要准备的资料整理如下: 1 域名未注册,建议在 阿里云注册:https://www.aliyun.com/,2 服务器https://ecs-buy.aliyun.com/配置:计费方式:包年包月地 ...

  3. django项目settings.py的基础配置

    一个新的django项目初始需要配置settings.py文件: 1. 项目路径配置 新建一个apps文件夹,把所有的项目都放在apps文件夹下,比如apps下有一个message项目,如果不进行此项 ...

  4. C# Task中的Func, Action, Async与Await的使用

    在说Asnc和Await之前,先说明一下Func和Action委托, Task任务的基础的用法 1. Func Func是一种委托,这是在3.5里面新增的,2.0里面我们使用委托是用Delegate, ...

  5. linux服务查看

    (1)#service servicename status比如查看防火墙:#service iptables status (2)#chkconfig --list |grep 服务名 比如查看te ...

  6. 解决SVN 每次操作都需要重输入用户名密码问题

    把目录C:\Users\当前账号\AppData\Roaming\Subversion\auth下的文件删除,然后重启hbuilder或eclipse工具,重新输入账号密码之后,保存即可解决该问题.

  7. SAP 生产订单变更管理 OCM Order Changement Management

    SAP OCM Order Changement Management  一.目的 订单变更管理系统是当我们的订单(生产订单.计划订单.采购订单)已经存在的时候,其物料主数据或销售数据有变更时,我们可 ...

  8. (原)关于udp的socket发送数据耗时的问题探讨

    转载请注明出处:http://www.cnblogs.com/lihaiping/p/6811791.html 本学习笔记,仅用于问题探讨,如有不同,可以讨论. 最近在看流媒体分发服务器的相关代码,其 ...

  9. ubuntu更改镜像源

    参考 https://blog.csdn.net/weixin_41762173/article/details/79480832 建议使用ustc.edu的源,其他例如清华的,阿里的连sublime ...

  10. Git命令行大全

    git branch 查看本地所有分支 git status 查看当前状态 git commit 提交 git branch -a 查看所有的分支 git branch -r 查看远程所有分支 git ...