day 12 装饰器
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 装饰器的更多相关文章
- Day 12 装饰器,开发封闭.
一.什么是装饰器 装饰器本质上就是一个python函数,他可以让其他函数在不需要做任何代码变动的前提下,增加额外的功能,装饰器的返回值也是一个函数对象. 装饰器的应用场景:比如插入日志,性能测试,事务 ...
- python 基础篇 12 装饰器进阶
本节主要内容:1. 通⽤装饰器回顾2. 函数的有⽤信息3. 带参数的装饰器4. 多个装饰器同时装饰⼀个函数 ⼀. 通⽤装饰器的回顾开闭原则: 对增加功能开放. 对修改代码封闭装饰器的作⽤: 在不改变原 ...
- 12装饰器及*args,**kwargs
注:参数和返回值都是一个函数. 1,无参数 def decotare1(func): def wrapper(): print("First") func() return wra ...
- 函数与装饰器Python学习(三)
1.1 文件处理 1.1.1 打开文件过程 在Python中,打开文件,得到文件句柄并赋值给一个变量,默认打开模式就为r f=open(r'a.txt','w',encoding='utf-8') p ...
- 详解python三大器——迭代器、生成器、装饰器
迭代器 聊迭代器前我们要先清楚迭代的概念:通常来讲从一个对象中依次取出数据,这个过程叫做遍历,这个手段称为迭代(重复执行某一段代码块,并将每一次迭代得到的结果作为下一次迭代的初始值). 可迭代对象(i ...
- python文章装饰器理解12步
1. 函数 在python中,函数通过def关键字.函数名和可选的参数列表定义.通过return关键字返回值.我们举例来说明如何定义和调用一个简单的函数: def foo(): return 1 fo ...
- day 12 - 1 装饰器进阶
装饰器进阶 装饰器的简单回顾 装饰器开发原则:开放封闭原则装饰器的作用:在不改变原函数的调用方式的情况下,在函数的前后添加功能装饰器的本质:闭包函数 装饰器的模式 def wrapper(func): ...
- 转载 12步轻松搞定python装饰器
作者: TypingQuietly 原文链接: https://www.jianshu.com/p/d68c6da1587a 呵呵!作为一名教python的老师,我发现学生们基本上一开始很难搞定pyt ...
- http://python.jobbole.com/85056/ 简单 12 步理解 Python 装饰器,https://www.cnblogs.com/deeper/p/7482958.html另一篇文章
好吧,我标题党了.作为 Python 教师,我发现理解装饰器是学生们从接触后就一直纠结的问题.那是因为装饰器确实难以理解!想弄明白装饰器,需要理解一些函数式编程概念,并且要对Python中函数定义和函 ...
随机推荐
- 补习系列(9)-springboot 定时器,你用对了吗
目录 简介 一.应用启动任务 二.JDK 自带调度线程池 三.@Scheduled 定制 @Scheduled 线程池 四.@Async 定制 @Async 线程池 小结 简介 大多数的应用程序都离不 ...
- 从0到1,了解NLP中的文本相似度
本文由云+社区发表 作者:netkiddy 导语 AI在2018年应该是互联网界最火的名词,没有之一.时间来到了9102年,也是项目相关,涉及到了一些AI写作相关的功能,为客户生成一些素材文章.但是, ...
- 《CLR via C#》读书笔记(一)——CLR的执行模式
前言 万事开头难,很早之前就想写博客记录些东西,迟迟未行动,甚是遗憾.原因诸多,大体上无非都是懒.没意志力等等.这次从自己的读书笔记开始,兴许能够有所改变. 一.CLR概念 CLR(Common La ...
- Java开发笔记(七十九)利用反射技术操作私有属性
早在介绍多态的时候,曾经提到公鸡实例的性别属性可能被篡改为雌性,不过面向对象的三大特性包含了封装.继承和多态,只要把性别属性设置为private私有级别,也不提供setSex这样的性别修改方法,那么性 ...
- ECMASCript 2019可能会有哪些特性?
最近这些年,ECMASCript标准发展节奏非常稳定,每年都会发布新的特性.那么,ECMASCript 2019可能会有哪些特性呢? ECMASCript语法提案的批准流程 JavaScript的标准 ...
- 17 , CSS 区块、浮动、定位、溢出、滚动条
1.CSS 中区块的使用 2.CSS 中浮动的使用 3.CSS 中定位的使用 4.CSS 中溢出的使用 5.CSS 中滚动条的使用 17.1 CSS 中区块的使用 属性名称 属性值 说明 width ...
- 前端项目git操作命名规范和协作开发流程
前言 一个项目的分支,一般包括主干 master 和 开发分支 dev,以及若干临时分支 分支命名规范 分支: 命名: 说明: 主分支 master 主分支,所有提供给用户使用的正式版本,都在这个主分 ...
- 字符串hash入门
简单介绍一下字符串hash 相信大家对于hash都不陌生 翻译过来就是搞砸,乱搞的意思嘛 hash算法广泛应用于计算机的各类领域,像什么md5,文件效验,磁力链接 等等都会用到hash算法 在信息学奥 ...
- 广州.NET微软技术俱乐部与其他技术群的区别
.NET和微软技术相关的微信群有不少, 那么广州.NET微软技术俱乐部与其他技术群的区别是什么呢? 有十分大的区别! 本群公告写得很清楚! 本群坚决禁止讨论“JAVA和.NET哪个好”.“NET有没有 ...
- MVP模式, 开源库mosby的使用及代码分析
Android中的构架模式一直是一个很hot的topic, 近年来Architecture components推出之后, MVVM异军突起, 风头正在逐渐盖过之前的MVP. 其实我觉得MVP还是有好 ...