20.python笔记之装饰器
装饰器
装饰器是函数,只不过该函数可以具有特殊的含义,装饰器用来装饰函数或类,使用装饰器可以在函数执行前和执行后添加相应操作。
装饰器是一个很著名的设计模式,经常被用于有切面需求的场景,较为经典的有插入日志、性能测试、事务处理等。装饰器是解决这类问题的绝佳设计,有了装饰器,我们就可以抽离出大量函数中与函数功能本身无关的雷同代码并继续重用。概括的讲,装饰器的作用就是为已经存在的对象添加额外的功能。
例:如果一个公司有运维部,开发部,测试部,设计部,等,并且公司具有基础平台架构,为公司各个部门提供数据库调用,资料查看,监控等。当这些部门想使用这些功能的时候,直接调用这些功能的接口就可以,如下:
基础平台提供的功能------------
def 功能1()
print ('功能1')
def 功能2()
print ('功能2')
def 功能3()
print ('功能3')
def 功能4()
print ('功能4')
当运维部门调用的时候如下:
def 功能1()
def 功能2()
def 功能3()
当开发部门调用的时候如下:
def 功能1()
def 功能2()
def 功能3()
之后要为平台提供的所有功能添加验证机制,
基础平台提供如下功能接口:
1.让各个部门修改自己的代码
2.在每个部门实现的功能上加上代码
3.把验证代码变成函数 在每个功能上加入
4.为了追寻开放封闭原则
利用装饰器的功能实现
def login(func):
def inner():
# 验证1
# 验证2
# 验证3
return func()
return inner
@login
def 功能1():
print ('功能1')
@login
def 功能2():
print ('功能2')
@login
def 功能3():
print ('功能3')
@login
def 功能4():
print ('功能4')
当各个部门执行def功能的时候
def login(func):
def inner():
# 验证1
return func()
return inner
@login
def 功能1():
print '功能1'
当调用功能1的时候 会先把功能1的函数名带入内存地址,之后会执行login函数,func为功能1,之后inner会将功能1的参数带入等待执行inner的验证功能后,会将参数交给func执行功能1的命令。
例:
第一步:最简单的函数,准备附加额外功能
def myfunc():
print("调用myfunc().")
myfunc()
myfunc()
结果:
调用myfunc().
调用myfunc().
第二步:使用装饰函数在函数执行前和执行后分别附加额外功能
def deco(func):
print("执行装饰器函数1")
func() #将func的内存地址执行
print("执行装饰器函数2")
return func #返回函数
def myfunc():
print(" 执行myfunc函数")
#执行deco函数的时候会把myfunc函数的内存地址带入
myfunc = deco(myfunc)
print(myfunc)
结果:
执行装饰器函数1
执行myfunc函数
执行装饰器函数2
<function myfunc at 0x0000000000BDA6A8>
第三步:使用语法糖@来装饰函数
def deco(func):
print("装饰器开始")
func()
print("装饰器结束")
return func
@deco
def myfunc():
print("我只是一个普通的函数")
或者:
def deco(func):
user = input('user:')
passwd = input('pass:')
print('验证成功')
func()
return func
#注func函数就是myfunc函数 当装饰器全部执行之后再执行func函数
@deco
def myfunc():
print("欢迎使用京猫平台")
第四步:使用内嵌包装函数来确保每次新函数都被调用
#内嵌包装函数的形参和返回值与原函数相同,装饰函数返回内嵌包装函数对象'''
def deco(func):
def _deco():
user = input('user:')
passwd = input('pass')
print('用户和密码正确')
func()
# 不需要返回func,实际上应返回原函数的返回值
return _deco
@deco
def login():
print("登录成功")
return 'ok'
#login函数可以重复调用多次,每次调用的时候,都会先执行装饰器里的函数,
login()
第五步:对带参数的函数进行装饰
#内嵌包装函数的形参和返回值与原函数相同,装饰函数返回内嵌包装函数对象'''
def deco(func):
def _deco(a, b):
ret = func(a, b)
return ret
return _deco
@deco
def myfunc(a, b):
print(" 函数%s+%s." % (a, b))
return a + b
myfunc(1, 2)
myfunc(3, 4)
#当我执行myfunc带参数的时候调用装饰器函数
第六步:对参数数量不确定的函数进行装饰
#参数用(*args, **kwargs),自动适应变参和命名参数'''
def deco(func):
def _deco(*args, **kwargs): #*agrs和**kwargs是普通函数的参数
print("普通函数名:%s" % func.__name__)
#执行普通函数
ret = func(*args, **kwargs)
print("普通函数%s执行结果为%s" % (func.__name__, ret))
return ret
return _deco
@deco
def myfunc(a, b):
print("普通函数1%s+%s" % (a, b))
return a+b
@deco
def myfunc2(a, b, c):
print("普通函数2%s+%s+%s" % (a, b, c))
return a+b+c
myfunc(1, 2)
myfunc(3, 4)
myfunc2(1, 2, 3)
myfunc2(3, 4, 5)
**第七步:让装饰器带参数**
#装饰函数名实际上应更有意义些'''
def deco(arg):
def _deco(func):
def __deco():
print("普通函数名 %s 装饰器参数名 [%s]." % (func.__name__, arg))
func()
print("普通函数名 %s 装饰器参数名 [%s]." % (func.__name__, arg))
return __deco
return _deco
@deco("装饰器参数1")
def myfunc():
print("普通函数1")
@deco("装饰器参数2")
def myfunc2():
print("普通函数2")
myfunc()
myfunc2()
第八步:装饰器带 类 参数
class locker:
def __init__(self):
print("这个是.__init__().")
@staticmethod
def acquire():
print("(这是静态方法)")
@staticmethod
def release():
print("(不需要对象实例)")
def deco(cls):
'''cls 必须实现acquire和release静态方法'''
def _deco(func):
def __deco():
print("函数名: %s 类:[%s]." % (func.__name__, cls))
cls.acquire()
try:
return func()
finally:
cls.release()
return __deco
return _deco
@deco(locker)
def myfunc():
print("普通函数")
myfunc()
**第九步:装饰器带类参数,并分拆公共类到其他py文件中,同时演示了对一个函数应用多个装饰器**
1.melocker.py(公共类文件)
class mylocker:
def __init__(self):
print("mylocker.__init__() called.")
@staticmethod
def acquire():
print("mylocker.acquire() called.")
@staticmethod
def unlock():
print(" mylocker.unlock() called.")
class lockerex(mylocker):
@staticmethod
def acquire():
print("lockerex.acquire() called.")
@staticmethod
def unlock():
print(" lockerex.unlock() called.")
def lockhelper(cls):
'''cls 必须实现acquire和release静态方法'''
def _deco(func):
def __deco(*args, **kwargs):
print("before %s called." % func.__name__)
cls.acquire()
try:
return func(*args, **kwargs)
finally:
cls.unlock()
return __deco
return _deco
2.使用装饰器文件
#!/usr/bin/env python3
#coding:utf8
from melocker import *
class example:
@lockhelpermelocker)
def myfunc(self):
print(" myfunc() called.")
@lockhelper(melocker)
@lockhelper(lockerex)
def myfunc2(self, a, b):
print(" myfunc2() called.")
return a + b
if __name__=="__main__":
a = example()
a.myfunc()
print(a.myfunc())
print(a.myfunc2(1, 2))
print(a.myfunc2(3, 4))
完毕!!!
20.python笔记之装饰器的更多相关文章
- python笔记 - day4-之装饰器
python笔记 - day4-之装饰器 需求: 给f1~f100增加个log: def outer(): #定义增加的log print("log") ...
- Python笔记:装饰器
装饰器 1.特点:装饰器的作用就是为已存在的对象添加额外的功能,特点在于不用改变原先的代码即可扩展功能: 2.使用:装饰器其实也是一个函数,加上@符号后放在另一个函数“头上”就实现了装饰 ...
- Python学习笔记:装饰器
Python 装饰器的基本概念和应用 代码编写要遵循开放封闭原则,虽然在这个原则是用的面向对象开发,但是也适用于函数式编程,简单来说,它规定已经实现的功能代码不允许被修改,但可以被扩展,即: 封闭:已 ...
- Noah的学习笔记之Python篇:装饰器
Noah的学习笔记之Python篇: 1.装饰器 2.函数“可变长参数” 3.命令行解析 注:本文全原创,作者:Noah Zhang (http://www.cnblogs.com/noahzn/) ...
- 第二篇:python高级之装饰器
python高级之装饰器 python高级之装饰器 本节内容 高阶函数 嵌套函数及闭包 装饰器 装饰器带参数 装饰器的嵌套 functools.wraps模块 递归函数被装饰 1.高阶函数 高阶函 ...
- Day11 Python基础之装饰器(高级函数)(九)
在python中,装饰器.生成器和迭代器是特别重要的高级函数 https://www.cnblogs.com/yuanchenqi/articles/5830025.html 装饰器 1.如果说装 ...
- 十. Python基础(10)--装饰器
十. Python基础(10)--装饰器 1 ● 装饰器 A decorator is a function that take a function as an argument and retur ...
- Python核心编程 | 装饰器
装饰器是程序开发的基础知识,用好装饰器,在程序开发中能够提高效率 它可以在不需要修改每个函数内部代码的情况下,为多个函数添加附加功能,如权限验证,log日志等 涉及点: 1.先梳理一下 ...
- 写python中的装饰器
python中的装饰器主要用于在已有函数实现功能前附加需要输出的信息,下面将用实例展示我如何写装饰器. 首先分别尝试写装饰器装饰一个无参函数和一个有参函数(被装饰函数仅输出,无返回值情况下) def ...
随机推荐
- 金融自助设备WOSA/XFS规范介绍
wosa(全称是windows开放式系统体系结构 windows open system architecture),是微软公司提出的一种在windows操作系统下的软件架构. wosa/xfs是基于 ...
- BZOJ-3211花神游历各国 并查集+树状数组
一开始想写线段树区间开方,简单暴力下,但觉得变成复杂度稍高,懒惰了,编了个复杂度简单的 3211: 花神游历各国 Time Limit: 5 Sec Memory Limit: 128 MB Subm ...
- TCP和Http的区别
相信不少初学手机联网开发的朋友都想知道Http与Socket连接究竟有什么区别,希望通过自己的浅显理解能对初学者有所帮助. 1.TCP连接 手机能够使用联网功能是因为手机底层实现了TCP/IP协议,可 ...
- POJ1860Currency Exchange(Bellman + 正权回路)
Currency Exchange Time Limit: 1000MS Memory Limit: 30000K Total Submissions: 23938 Accepted: 867 ...
- nl命令详解
nl命令在linux系统中用来计算文件中行号.nl 可以将输出的文件内容自动的加上行号!其默认的结果与 cat -n 有点不太一样, nl 可以将行号做比较多的显示设计,包括位数与是否自动补齐 0 等 ...
- TCP的那些事儿(上)
TCP的那些事儿(上) 原文链接:http://coolshell.cn/articles/11564.html TCP是一个巨复杂的协议,因为他要解决很多问题,而这些问题又带出了很多子问题和阴暗面. ...
- 6种编写HTML和CSS的最有效的方法
感谢HTML5和CSS3,以及JavaScript,前端开发者有了大大的用武之地.大家都在用很多的工具和技术来武装自己,以加快前段的开发. 本文分享了6中最有效的方法,希望能提供你的效率,为你节约时间 ...
- const 与 readonly的区别
首先先解释下什么是静态常量以及什么是动态常量. 静态常量是指编译器在编译时候会对常量进行解析,并将常量的值替换成初始化的那个值. 动态常量的值则是在运行的那一刻才获得的,编译器编译期间将其标示为只读常 ...
- 未能正确加载“Microsoft.VisualStudio.Editor.Implementation.EditorPackage,
未能正确加载“Microsoft.VisualStudio.Editor.Implementation.EditorPackage, Microsoft.VisualStudio.Editor.Imp ...
- CNN 美国有线电视新闻网 wapCNN WAP 指无线应用通讯协议 ---- 美国有线电视新闻网 的无线应用
wapCNN wap指无线应用通讯协议 CNN美国有线电视新闻网 固, wapCNN 美国有线电视新闻网的无线应用 -------------------------------------- ...