装饰器

装饰器是函数,只不过该函数可以具有特殊的含义,装饰器用来装饰函数或类,使用装饰器可以在函数执行前和执行后添加相应操作。

装饰器是一个很著名的设计模式,经常被用于有切面需求的场景,较为经典的有插入日志、性能测试、事务处理等。装饰器是解决这类问题的绝佳设计,有了装饰器,我们就可以抽离出大量函数中与函数功能本身无关的雷同代码并继续重用。概括的讲,装饰器的作用就是为已经存在的对象添加额外的功能。

例:如果一个公司有运维部,开发部,测试部,设计部,等,并且公司具有基础平台架构,为公司各个部门提供数据库调用,资料查看,监控等。当这些部门想使用这些功能的时候,直接调用这些功能的接口就可以,如下:

基础平台提供的功能------------

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笔记之装饰器的更多相关文章

  1. python笔记 - day4-之装饰器

                 python笔记 - day4-之装饰器 需求: 给f1~f100增加个log: def outer(): #定义增加的log print("log") ...

  2. Python笔记:装饰器

    装饰器        1.特点:装饰器的作用就是为已存在的对象添加额外的功能,特点在于不用改变原先的代码即可扩展功能: 2.使用:装饰器其实也是一个函数,加上@符号后放在另一个函数“头上”就实现了装饰 ...

  3. Python学习笔记:装饰器

    Python 装饰器的基本概念和应用 代码编写要遵循开放封闭原则,虽然在这个原则是用的面向对象开发,但是也适用于函数式编程,简单来说,它规定已经实现的功能代码不允许被修改,但可以被扩展,即: 封闭:已 ...

  4. Noah的学习笔记之Python篇:装饰器

    Noah的学习笔记之Python篇: 1.装饰器 2.函数“可变长参数” 3.命令行解析 注:本文全原创,作者:Noah Zhang  (http://www.cnblogs.com/noahzn/) ...

  5. 第二篇:python高级之装饰器

    python高级之装饰器   python高级之装饰器 本节内容 高阶函数 嵌套函数及闭包 装饰器 装饰器带参数 装饰器的嵌套 functools.wraps模块 递归函数被装饰 1.高阶函数 高阶函 ...

  6. Day11 Python基础之装饰器(高级函数)(九)

    在python中,装饰器.生成器和迭代器是特别重要的高级函数   https://www.cnblogs.com/yuanchenqi/articles/5830025.html 装饰器 1.如果说装 ...

  7. 十. Python基础(10)--装饰器

    十. Python基础(10)--装饰器 1 ● 装饰器 A decorator is a function that take a function as an argument and retur ...

  8. Python核心编程 | 装饰器

        装饰器是程序开发的基础知识,用好装饰器,在程序开发中能够提高效率 它可以在不需要修改每个函数内部代码的情况下,为多个函数添加附加功能,如权限验证,log日志等   涉及点:   1.先梳理一下 ...

  9. 写python中的装饰器

    python中的装饰器主要用于在已有函数实现功能前附加需要输出的信息,下面将用实例展示我如何写装饰器. 首先分别尝试写装饰器装饰一个无参函数和一个有参函数(被装饰函数仅输出,无返回值情况下) def ...

随机推荐

  1. TinyMCE(富文本编辑器)

    [转]TinyMCE(富文本编辑器)在Asp.Net中的使用方法 官网演示以及示例代码:https://www.tinymce.com/docs/demo/image-tools/ 转自:http:/ ...

  2. oracle存储过程执行中输出日志文件

    create or replace procedure p_outputdebug(a varchar2,b varchar2,c varchar2)is vFileName varchar2(100 ...

  3. JEECMS插件开发

    在jeecms框架中,有一个简单的插件,它并没有写具体的功能实现,但可以从这个简单的插件中找到如何在jeecms框架中开发框架的方法.      首先创建一个jeecms的框架demo,登录jeecm ...

  4. MySQL安装最后一步apply security settings错误

    网上查了很久都是说删除各种文件什么的,直接百度apply security settings,说是mysql没卸载干净.不是的. 看日志发现 You must SET PASSWORD before ...

  5. 使用U盘安装mint

    系统坏了,重新装的时候,硬盘甚至都没法格式化...所以,狠狠心买了块固态硬盘,123G,威刚. 想自己装Linux系统,这样用起来更方便一点,不用装虚拟机,然后再跑linux什么的.最后选了mint. ...

  6. 深入浅出MySQL双向复制技术

    设置MySQL数据同步(单向&双向)由于公司的业务需求,需要网通和电信的数据同步,就做了个MySQL的双向同步,记下过程,以后用得到再翻出来,也贴出来供大家参考. 一.准备服务器 由于MySQ ...

  7. 解决微信OAuth2.0网页授权回调域名只能设置一个的问题

    https://github.com/HADB/GetWeixinCode GetWeixinCode 解决微信OAuth2.0网页授权回调域名只能设置一个的问题 使用方法 部署get-weixin- ...

  8. shell的内建命令和外部命令

    shell的内建命令和外部命令 Shell执行的命令可以分为内建命令(built-in)和外部命令(external),前者是构建在shell内部:后者是一个独立的文件(可以是二进制文件,也可以是一个 ...

  9. WebSocket 基本函数

    1.构造函数   WebSocket(char *host); 创建一个websocket对象,接受一个参数以ws://靠头,就像发起一个HTTP请求一样用http://开头 var ws=new W ...

  10. Linux中iptables设置详细(转)

    无论如何,iptables是一个需要特别谨慎设置的东西,万一服务器不在你身边,而你贸然设置导致无法SSH,那就等着被老板骂吧,呵呵... 以下内容是为了防止这种情况发生而写的,当然很初级,不过一般服务 ...