nonlocal关键字

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

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

# 案例:

def outer():
   num = 10
   print(num)  # 10
   def inner():
       nonlocal num
       num = 20
       print(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()

wraps修改函数文档注释

from functools import wraps
def outer(func):
   @wraps(func)
   def inner(*args, **kwargs):
       '''装饰器文档注释'''
       func(*args, **kwargs)
   return inner

@outer
def func(*args, **kwargs):
   '''原有文档注释'''
   print("原有功能")
print(func.__doc__)  #__doc__方法查看文档注释
 

登录认证功能

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. Day 12 装饰器,开发封闭.

    一.什么是装饰器 装饰器本质上就是一个python函数,他可以让其他函数在不需要做任何代码变动的前提下,增加额外的功能,装饰器的返回值也是一个函数对象. 装饰器的应用场景:比如插入日志,性能测试,事务 ...

  2. python 基础篇 12 装饰器进阶

    本节主要内容:1. 通⽤装饰器回顾2. 函数的有⽤信息3. 带参数的装饰器4. 多个装饰器同时装饰⼀个函数 ⼀. 通⽤装饰器的回顾开闭原则: 对增加功能开放. 对修改代码封闭装饰器的作⽤: 在不改变原 ...

  3. 12装饰器及*args,**kwargs

    注:参数和返回值都是一个函数. 1,无参数 def decotare1(func): def wrapper(): print("First") func() return wra ...

  4. 函数与装饰器Python学习(三)

    1.1 文件处理 1.1.1 打开文件过程 在Python中,打开文件,得到文件句柄并赋值给一个变量,默认打开模式就为r f=open(r'a.txt','w',encoding='utf-8') p ...

  5. 详解python三大器——迭代器、生成器、装饰器

    迭代器 聊迭代器前我们要先清楚迭代的概念:通常来讲从一个对象中依次取出数据,这个过程叫做遍历,这个手段称为迭代(重复执行某一段代码块,并将每一次迭代得到的结果作为下一次迭代的初始值). 可迭代对象(i ...

  6. python文章装饰器理解12步

    1. 函数 在python中,函数通过def关键字.函数名和可选的参数列表定义.通过return关键字返回值.我们举例来说明如何定义和调用一个简单的函数: def foo(): return 1 fo ...

  7. day 12 - 1 装饰器进阶

    装饰器进阶 装饰器的简单回顾 装饰器开发原则:开放封闭原则装饰器的作用:在不改变原函数的调用方式的情况下,在函数的前后添加功能装饰器的本质:闭包函数 装饰器的模式 def wrapper(func): ...

  8. 转载 12步轻松搞定python装饰器

    作者: TypingQuietly 原文链接: https://www.jianshu.com/p/d68c6da1587a 呵呵!作为一名教python的老师,我发现学生们基本上一开始很难搞定pyt ...

  9. http://python.jobbole.com/85056/ 简单 12 步理解 Python 装饰器,https://www.cnblogs.com/deeper/p/7482958.html另一篇文章

    好吧,我标题党了.作为 Python 教师,我发现理解装饰器是学生们从接触后就一直纠结的问题.那是因为装饰器确实难以理解!想弄明白装饰器,需要理解一些函数式编程概念,并且要对Python中函数定义和函 ...

随机推荐

  1. List-ArrayList集合基础增强底层源码分析

    List集合基础增强底层源码分析 作者:Stanley 罗昊 [转载请注明出处和署名,谢谢!] 集合分为三个系列,分别为:List.set.map List系列 特点:元素有序可重复 有序指的是元素的 ...

  2. 初学Java Web(5)——cookie-session学习

    HTTP 协议 Web 浏览器与 Web 服务器之间的一问一答的交互过程必须遵守一定的规则,这样的规则就是 HTTP 协议. HTTP 是 hypertext transfer protocol(超文 ...

  3. 适配器模式 adapter 结构型 设计模式(九)

    现实世界中的适配器模型   先来看下来几个图片,截图自淘宝 上图为港版的插头与港版的插座   上图为插座适配器卖家的描述图   上图为适配后的结果 现实世界中适配器模式 角色分类 这就是适配器模式在电 ...

  4. 根据数值获得概率密度pdf和累积密度分布cdf(MATLAB语言)

    y=randn(1,3000); % 生成1-by-3000的标准正态分布随机数 ymin=min(y); ymax=max(y); x=linspace(ymin,ymax,20); %将最大最小区 ...

  5. MySQL 笔记整理(5) --深入浅出索引(下)

    笔记记录自林晓斌(丁奇)老师的<MySQL实战45讲> 5) --深入浅出索引(下) 这次的笔记从一个简单的查询开始: 建表语句是这样的 mysql> create table T ...

  6. 使用顶级 VSCode 扩展来加快开发 JavaScript

    使用顶级 VSCode 扩展来加快开发 JavaScript 发表于 2018年08月24日 by 愚人码头 被浏览 3,942 次 分享到:   小编推荐:掘金是一个面向程序员的高质量技术社区,从 ...

  7. C# ListBox实现显示插入最新的数据的方法

    在我们使用ListBox控件时,如果我们在里面不断的添加一条条数据,但是在我们添加的数据过多超过了ListBox显示的窗口时(此时会产生滑动条), 发现我们无法看到最新添加的数据.实现倒序显示此处有两 ...

  8. Python全栈开发之---assert断言

    一.python assert的作用: 根据Python 官方文档解释(https://docs.python.org/3/reference/simple_stmts.html#assert), & ...

  9. bitset中_Find_first()与_Find_next()函数

    bitset中_Find_first()与_Find_next()函数 很有趣但是没怎么有用的两个函数. _Find_fisrt就是找到从低位到高位第一个1的位置 #include<bits/s ...

  10. 文件类型解析漏洞防御与攻击(PHP)

    简介: 解析漏洞主要是一些特殊文件被iis.Apache.Nginx等服务在某种情况下解释成脚本文件格式并得以执行而产生的漏洞,一般的思路都是用图片木马来欺骗服务器,上传webshell,达到提权的目 ...