nonlocal关键字

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

开放封闭原则:不改变调用方式与源代码上增加功能

'''
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 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 check_usr(fn):  # fn, login, inner:不同状态下的login,所以参数是统一的
   def inner(usr, pwd):
       # 在原功能上添加新功能
       if not (len(usr) >= 3 and usr.isalpha()):
           print('账号验证失败')
           return False
       
       # 原有功能
       result = fn(usr, pwd)
       
  # 在原功能下添加新功能
       # ...
       
       return result
  return inner
​
​
@check_usr
def login(usr, pwd):
   if usr == 'abc' and pwd =='123qwe':
       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的返回值
"""

装饰器最终写法

​
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('fn3的原有功能')
   return True
@wrap
def fn4(a, *, x):
   print('fn4的原有功能')
   return True
​
fn1()
fn2(10, 20)
fn3()
fn4(10, x=20)

带参装饰器:了解

# 了解
def outer(input_color):
   def wrap(fn):
       if input_color == 'red':
           info = '\033[36;41mnew 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: ')
@outer(color)  # @outer(color) ==> @wrap # func => inner
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('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()

Day 12 开放封闭原则,装饰器初识的更多相关文章

  1. day12 十二、开放封闭、装饰器

    一.nonlocal关键词 # global # num = # def fn(): # global num # L>G 将局部的名字与全局统一 # num = # fn() # print( ...

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

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

  3. Python——day12 nonlcoal关键字、装饰器(开放封闭原则、函数被装饰、最终写法)

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

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

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

  5. day11.装饰器初识

    1.开放封闭原则 原则: 开放封闭原则,对扩展是开放的,对修改是封闭的. 封版概念:当写好一个功能以后,就不可以再修改此函数,避免下面一系列的调用产生错误. 因此产生了装饰器 2.装饰器形成过程 我们 ...

  6. DAY 13 开放封闭原则

    装饰器: 即是用一个函数去拓展另一个函数,同时遵循开放封闭原则 开放封闭原则 对修改关闭,对拓展开放 不允许修改源代码以及调用方式 以下是无参函数的基本格式 def outer(func): def ...

  7. python 装饰器-初识

    一.装饰器的形成过程 1.函数无参数,无返回值 import time def f1(): # 无参数,无返回值 time.sleep(1) print("Hello, World!&quo ...

  8. python 全栈开发,Day11(函数名应用,闭包,装饰器初识,带参数以及带返回值的装饰器)

    一.函数名应用 函数名是什么?函数名是函数的名字,本质:变量,特殊的变量. 函数名(),执行此函数. python 规范写法 1. #后面加一个空格,再写内容,就没有波浪线了. 2.一行代码写完,下面 ...

  9. (转) 面向对象设计原则(二):开放-封闭原则(OCP)

    原文:https://blog.csdn.net/tjiyu/article/details/57079927 面向对象设计原则(二):开放-封闭原则(OCP) 开放-封闭原则(Open-closed ...

随机推荐

  1. Angular4.x Event (DOM事件和自定义事件)

    Angular组件和DOM元素通过事件与外部进行通信,两者中的事件绑定语法是相同的-(eventName)="expression": <button (click)=&qu ...

  2. 安装Go插件遇到的问题及解决方法

    1. 问题:在 Windows 平台下使用 go get 安装sqlite3 驱动时报错 The remote end hung up unexpectedly ? 原因及解决方法: 原因可能有两种: ...

  3. linux存储管理之磁盘阵列

    磁盘阵列 RAID ====================================================================================RAID:廉 ...

  4. querySelector() 方法

    返回文档中匹配指定 CSS 选择器的一个元素. 虽然IE8中没有getElementsByClassName()但可以用querySelector()代替 注意: querySelector() 方法 ...

  5. python3-连接MySQL(mysql.connector与MySQLdb区别)

    import mysql.connector cnx = mysql.connector.connect(user='scott', password='tiger',host='127.0.0.1' ...

  6. 【HTML入门基础知识】从零开始,我要加油!---致HTML

    前言: 今天来和大家分享一下近期自己整理的HTML笔记,希望会对你的学习有所帮助! ***本章关键词:HTML头部格式:常见的块级标签:常见的行级标签:表格:表单. 一.HTML头部格式 一.HTML ...

  7. Win10系列:C#应用控件基础15

    ProgressRing控件 上一小节讲解了ProgressBar控件的使用方法,ProgressRing控件和ProgressBar控件都是用来显示应用程序当前任务的运行进度信息,区别在于Progr ...

  8. GDAL源码编译(32位)

    GDAL源码编译(32位) 前言 GDAL:GDAL/OGR 是一个地理空间数据的格式转换及处理工具.官网:https://www.gdal.org/ swig:SWIG是个帮助使用C或者C++编写的 ...

  9. Vue调用百度接口做百度搜索

    这两天由于学习需要,需要用vue来调用api接口,但是以前没怎么接触过用vue来调用接口,不会没关系,发挥我们强大的学习能力,都不是事,学习了半天基本也就可以初级上手了,写篇随笔记录下来,方便以后回顾 ...

  10. leetcode 总结 动态规划问题小结

    动态规划 动态规划对于子问题重叠的情况特别有效,因为它将子问题的解保存在表格,当需要某个子问题的解 时,直接取值即可,从而避免重复计算. 基本思路与策略 基本思想与分治法类似,也是将带求解的问题分解为 ...