一、nonlocal关键字

1、作用:将L与E(E中的名字需要提前定义)的名字统一

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

  1. def outer():
  2. num=10
  3. print(num) # 输出结果为10
  4. def inner():
  5. nonlocal num
  6. num=20
  7. print(num) #输出级结果为20
  8. inner()
  9. print(num) # 输出结果为20
  1. def outer():
  2. num= # 必要写 是用于L与E的名字统一
  3. def inner():
  4. # 如果想被嵌套的函数中修改外部函数变量(名字)的值
  5. nonlocal num # 将L与E(E中的名字需提前定义好)的名字统一
  6. num=
  7. print(num) # 输出结果为10
  8. inner()
  9. print(num ) # 定义了nonlocal就是局部统一,输出结果为10
  10. outer()
  11. # print(num)# 属于全局,不能看到其值

二、开放封闭原则

  1. 1、原则: 不能修改被装饰对象(函数)的源代码——封闭
    不能更改被修饰对象(函数)的调用方式,且能达到增加功能的效果——开放
  1. .0版本
  2. def fn():
  3. print('fn run ')
  4. fn()
  5.  
  6. 版本2.
  7. def fn2():
  8. print('fn run 0')
  9. print('fn run1')
  10. print('fn run2')
  11.  
  12. 修改了源代码,没有更改调用方式,对外调用方式还是原来的,
  13. def fn():
  14. print('fn run0')
  15. print('fn run ')
  16. print('fn run2')
  17.  
  18. 更改了调用方式,没有修改原功能代码块
  19. def wrap(fn):
  20. print('fn run0')
  21. fn()
  22. print('fn run2')
  23. wrap(fn)

三、装饰器

  1. 1、定义:就是闭包(闭包的一个应用场景)
          把要装饰的函数作为外部函数的参数通过闭包操作返回一个替代版函数1
  2.  
  3. 2、优点:丰富了原有函数的功能
           提高了程序的可拓展性
  4.  
  5. 把要被装饰的函数作为外层函数的参数通过闭包操作后返回一个替代版函数
    被装饰的函数:fn
    外层函数:outerfunc)、outerfn)==》func=fn
    替代版函数;return inner:原有功能加新功能
  1. def fn():
  2. print('原有功能')
  3.  
  4. # 装饰器
  5. def outer(tag):
  6. def inner():
  7. tag()
  8. print('新增功能')
  9. return inner
  10. fn=outer(fn)
  11. fn()
  1. 案例 花瓶
  2. def vase():
  3. print('插花')
  4. vase()
  5.  
  6. 增加一个绘画后观赏功能
  7. def wrap(fn):
  8. vase()
  9. print('插花')
  10. print('绘画:进行观赏')
  11. wrap(vase)
  12.  
  13. 虽然满足了开放封闭原则,但出现了函数调用死循环
  14.  
  15. def fn():
  16. vase()
  17. print('绘画:进行观赏')
  18. vase=fn()
  19. vase()
  20.  
  21. 了解:满足开放fengbiyuanze,且可以达到装饰器的作用:拓展功能
  22. tag=vase # 暴露在全局:
  23. def fn():
  24. tag()
  25. print('绘画:进行观赏')
  26. vase=fn
  27. vase()
  28.  
  29. 满足开放封闭原则(完美方法)
  30. 方式一
  31. def wrap (tag):
  32. tag=vase
  33. def fn():
  34. tag()
  35. print('绘画:进行观赏')
  36. return fn # 拓展功能后的vase
  37. vase =wrap() # 相当于vase=fn
  38. vase()
  39.  
  40. 方式二、这个函数嵌套结构就是装饰器
  41. def wrap (tag):
  42. def fn():
  43. tag() # 指原有的vase
  44. print('绘画:进行观赏')
  45. return fn # 拓展功能后的vase
  46. vase =wrap(vase) # 将拓展功能后的函数重新赋值给vase
  47. vase() # 功能拓展了,且调用方式不变

四、装饰器的简化语法

  1. ef outer(f):
  2. def inner():
  3. f()
  4. print("新增功能1")
  5. return inner
  6.  
  7. def wrap(f):
  8. def inner():
  9. f()
  10. print("新增功能2")
  11. return inner
  12.  
  13. @wrap # 被装饰的顺序决定了新增功能的执行顺序
  14. @outer # <==> fn = outer(fn): inner
  15. def fn():
  16. print("原有功能")
  1. 案例:
  2.  
  3. def outer (fn):
  4. def inner():
  5. fn()
  6. print('绘画:进行观赏')
  7. return inner
  8.  
  9. def wrse (fn):
  10. def inner():
  11. fn()
  12. print('摆放功能')
  13. return inner
  14.  
  15. @语法糖|笑笑语法
  16.  
  17. @wrse
  18. @outer #等于这个功能<==>vase =outer(vase)
  19. def vase():
  20. print('插花')
  21. vase()
  22.  
  23. 总结:一个函数可以被任意一个相关装饰器装饰,也可以被任意几个装饰器装饰
  24. 注:装饰的顺序会影响新增功能的执行顺序

五、有参有返的函数被修饰

  1. def check_usr(fn):# fn,login,inner:不同状态下的login,所以参数是统一的
  2. def inner(usr,pwd):
  3. # 在原功能上添加新功能
  4. if not(len(usr)>=3and usr.isalpha()):
  5. print('账号验证失败')
  6. return False
  7. # 原有功能
  8. result=fn(usr,pwd)
  9. # 在原功能下添加新功能
  10. #。。。。。()没有添加则用句号省略了
  11. return result
  12. return inner
  13.  
  14. @check_usr
  15. def login(usr,pwd):
  16. if usr=='abc'and pwd=='123abc':
  17. print('登录成功')
  18. return True
  19. print('登录失败')
  20. return False
  21.  
  22. 总结:1login有参数,所以innerfn都有相同参数
  1. 2login有返回值,所以innerfn都有返回值
  2.  
  3. inner(usr, pwd):
    res = fn(usr, pwd) # 原login的返回值
    return res
  4.  
  5. login = check_usr(login) = inner
  6.  
  7. res = login('abc', '123qwe') # inner的返回值
  1. 案例:
  2.  
  3. 增加一个账号处理功能:3位以上英文字符或汉字
  4.  
  5. def check_usr(fn):
  6. def inner(usr,pwd):
  7. if not (len(usr)>=3 and usr.isalpha()):
  8. print('账号验证失败')
  9. return False
  10. result=fn(usr,pwd) #login
  11. return result
  12. return inner
  13.  
  14. 增加一个密码处理功能:6位以上英文和数字
  15. def check_pwd(fn):
  16. def inner(usr,pwd):
  17. if not (len(pwd)>=6 and pwd.isalnum()):
  18. print('密码验证失败')
  19. return False
  20. return fn(usr,pwd) #result=fn(usr,pwd) return result
  21. return inner
  22.  
  23. 登录功能
  24. @check_usr # login=check_usr(login)=inner
  25. def login(usr,pwd):
  26. if usr=='abc' and pwd=='123abc':
  27. print('登录成功')
  28. print('登录失败')
  29. return False
  30.  
  31. res=login('abc','123abc') # inner 用户名和密码正确输出验证成功
  32. print(res)

六、装饰器的最终写法

  1. # 装饰器的最终写法
  2. def wrap (fn):
  3. def inner(*args,**kwargs):
  4. print('前增功能')
  5. result =fn(*args,**kwargs)
  6. print('后增功能')
  7. return result
  8. return inner
  9.  
  10. @wrap
  11. def fn1():
  12. print('fn1的原有功能')
  13. @wrap
  14. def fn2(a,b): # 有参数无值
  15. print('fn2的原有功能')
  16.  
  17. @wrap
  18. def fn3():# 有返回值无参数
  19. print('fn2的原有功能')
  20. return True
  21. @wrap
  22. def fn4(a,*,c): #有参数有返回值
  23. print('fn2的原有功能')
  24. return True
  25.  
  26. fn1()
  27. fn2(10,20)
  28. fn3()
  29. fn4(10,c=20)
  30.  
  31. 案例:
  32. 增加一个账号处理功能:3位及以上英文字符或汉字
  33. def check_usr(fn):
  34. def inner(usr,pwd):
  35. if not(len(usr)>=3 and usr.isalpha()):
  36. print('账号验证失败')
  37. return False
  38. result=fn(usr,pwd) #login
  39. return result
  40. return inner
  41.  
  42. 登录功能
  43. @check_usr
  44. def login(usr,pwd):
  45. if usr=='abc'and pwd=='123abc':
  46. print('登录成功')
  47. return True
  48. print('登录失败')
  49. return False
  50.  
  51. res=login('abc','123abc') #inner 账号密码正确打印成功
  52. print(res)
  1. 带参装饰器
  2.  
  3. def outer(input_color):
  4. def wrap(fn):
  5. if input_color=='red':
  6. info='\033[36;41m new action\33[0m'
  7. else:
  8. info='yellow:new action'
  9. def inner(*args,**kwargs):
  10. pass
  11. result=fn(*args,**kwargs)
  12. print(info)
  13. return result
  14. return inner
  15. return wrap #outer(color)=>>wrap
  16.  
  17. color=input('color:')
  18.  
  19. def func():
  20. print('func run')
  21. func()

七、登录认证案例

  1. is_login=False #登录状态
  2. def login():
  3. usr=input('usr:')
  4. if not(len(usr)>=3 and usr.isalpha()):
  5. print('账号验证失败')
  6. return False
  7. pwd=input('ped:')
  8. if usr=='abc'and pwd=='123abc':
  9. print('登录成功')
  10. is_login=True
  11. else:
  12. print('登录失败')
  13. is_login=False
  14.  
  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.  
  27. 查看个人主页功能
  28. @check_login
  29. def home():
  30. print('个人主页')
  31.  
  32. 销售功能
  33. @check_login
  34. def sell():
  35. print('可以销售')
  36. home()

Python——day12 nonlcoal关键字、装饰器(开放封闭原则、函数被装饰、最终写法)的更多相关文章

  1. 【Python入门学习】闭包&装饰器&开放封闭原则

    1. 介绍闭包 闭包:如果在一个内部函数里,对在外部作用域的变量(不是全局作用域)进行引用,那边内部函数被称为闭包(closure) 例如:如果在一个内部函数里:func2()就是内部函数, 对在外部 ...

  2. python 装饰器 对类和函数的装饰

    #装饰器:对类或者函数进行功能的扩展  很多需要缩进的没有进行缩进'''#第一步:基本函数def laxi(): print('拉屎')#调用函数laxi()laxi() print('======= ...

  3. Day 12 开放封闭原则,装饰器初识

    nonlocal关键字 # 作用:将 L 与 E(E中的名字需要提前定义) 的名字统一​# 应用场景:如果想在被嵌套的函数中修改外部函数变量(名字)的值​# 案例:​def outer():    n ...

  4. 装饰器和"开放-封闭"原则

    装饰器和"开放-封闭"原则 "开放-封闭"原则 软件开发中的"开放-封闭"原则,它规定已经实现的功能代码不应该被修改,但可以被扩展,即: 封 ...

  5. 【Python 函数对象 命名空间与作用域 闭包函数 装饰器 迭代器 内置函数】

    一.函数对象 函数(Function)作为程序语言中不可或缺的一部分,但函数作为第一类对象(First-Class Object)却是 Python 函数的一大特性. 那到底什么是第一类对象(Firs ...

  6. Python装饰器、内置函数之金兰契友

    装饰器:装饰器的实质就是一个闭包,而闭包又是嵌套函数的一种.所以也可以理解装饰器是一种特殊的函数.因为程序一般都遵守开放封闭原则,软件在设计初期不可能把所有情况都想到,所以一般软件都支持功能上的扩展, ...

  7. Python学习之路基础篇--11-12Python基础,函数的装饰器

    对于装饰器来说,就是在不改变函数的调用的情况下,对函数的前后增加了些许功能,这完全符合函数的 开放封闭 原则.装饰器的本质 其实就是一个闭包函数. 这是一个装饰器的步骤图 ret = func(*ar ...

  8. python函数知识七 闭包、装饰器一(入门)、装饰器二(进阶)

    21.闭包 闭包:在嵌套函数内,使用非全局变量(且不使用本层变量) 闭包的作用:1.保证数据的安全性(纯洁度).2.装饰器使用 .__closure__判断是否是闭包 def func(): a = ...

  9. python 装饰器(四):装饰器基础(三)叠放装饰器,参数化装饰器

    叠放装饰器 示例 7-19 演示了叠放装饰器的方式:@lru_cache 应用到 @clock 装饰fibonacci 得到的结果上.在示例 7-21 中,模块中最后一个函数应用了两个 @htmliz ...

随机推荐

  1. Python 官方文档解读(1):66 个内置函数

    Python 解释器 (CPython 3.7)内置有 66 个函数,这些函数在任何时刻都是可用的.此文是为了对这 66 个函数进行简单的梳理,便于以后可能用到它们时能想到. 1. abs(x) 返回 ...

  2. MongoDB,从数组中删除对象

    { _id: 5150a1199fac0e6910000002, name: 'some name, items: [{ id: 23, name: 'item name 23' },{ id: 24 ...

  3. Oracle表导入Mysql方法

    public void reportPerInfo(){ //每次导入清除之前数据 this.esEntPermitErrDao.updateObjectBySql("delete from ...

  4. FFT快速傅里叶变换算法

    1.FFT算法概要: FFT(Fast Fourier Transformation)是离散傅氏变换(DFT)的快速算法.即为快速傅氏变换.它是根据离散傅氏变换的奇.偶.虚.实等特性,对离散傅立叶变换 ...

  5. python no module named _socket 原因

    python no module named _socket 原因 Lib/site-packages 不在 sys.path 中

  6. vue-cli3.0安装element-ui组件及按需引入element-ui组件

    在VUE-CLI 3下的第一个Element-ui项目(菜鸟专用) (https://www.cnblogs.com/xzqyun/p/10780659.html) 上面这个链接是vue-cli3.0 ...

  7. angular之指令

    指令(Directive) 1.指令概念介绍 --  AngularJS有一套完整的.可扩展的.用来帮助web应用开发的指令集. --  在DOM编译期间和HTML关联着的指令会被检测到,并且 会被执 ...

  8. git 修改用户名和密码

    初次运行 Git 前的配置 一般在新的系统上,我们都需要先配置下自己的 Git 工作环境.配置工作只需一次,以后升级时还会沿用现在的配置.当然,如果需要,你随时可以用相同的命令修改已有的配置. Git ...

  9. [CF364D]Ghd

    [CF364D]Ghd 题目大意: 有\(n(n\le10^6)\)个数\(A_{1\sim n}(A_i\le10^{12})\),从中选取\(\lceil\frac n2\rceil\)个数,使得 ...

  10. Python数据分析实战

    Python数据分析实战(高清版)PDF 百度网盘 链接:https://pan.baidu.com/s/1nlHM1IW8MYg3z79TUwIsWg 提取码:ux8t 复制这段内容后打开百度网盘手 ...