Python 装饰器

装饰器函数

#装饰器:在不改变函数的调用方式的情况下,给函数的前后添加新的功能。#

有的时候写完一段代码,过段时间需要对它进行升级、添加一些新功能,但是如果要直接修改原来的代码会影响其他人的调用,所以就需要一个不修改源代码且不修改原函数的调用方式的东西,又能为原函数增添新功能的东西,装饰器就是干这个的。(装饰器的本质其实是个闭包函数)

##复习:闭包;内部函数使用外部函数中的变量,这种情况下就称这是一个闭包。

def f1(b):
    def f2():
        print(b)
    f2()
    return f2
ff=f1('bbb')
ff()
# bbb
# bbb

 

####上例中timer()就是一个装饰器函数,f()就是被装饰函数

1)为什么要用装饰器

#开放封闭原则:对修改封闭,对扩展开放

2)什么是装饰器

装饰器他人的器具,本身可以是任意可调用对象,被装饰者也可以是任意可调用对象。
强调装饰器的原则:1 不修改被装饰对象的源代码 2 不修改被装饰对象的调用方式
装饰器的目标:在遵循1和2的前提下,为被装饰对象添加上新功能

 原则: 开放封闭原则  

   开放 : 对扩展是开放的
封闭 : 对修改是封闭
# timmer就是一个装饰器函数,对一个函数 有一些装饰作用
import time
def timmer(f):    #装饰器函数
    def inner():
        start = time.time()
        ret = f()       #被装饰的函数
        end = time.time()
        print(end - start)
        return ret
    return inner

@timmer         #语法糖 @装饰器函数名
def func():     #被装饰的函数
    time.sleep(0.01)
    print('老板好同事好大家好')
    return '新年好'
# func = timmer(func)
ret = func()   #inner()
print(ret)
###
老板好同事好大家好
0.010995864868164062
新年好

3)装饰带参数函数的装饰器

import time
def timmer(f):    #装饰器函数
    def inner(*args,**kwargs):
        #(1,2) /(1)
        start = time.time()
        ret = f(*args,**kwargs)  #f(1,2)       #被装饰的函数
        end = time.time()
        print(end - start)
        return ret
    return inner

@timmer         #语法糖 @装饰器函数名
def func(a,b):     #被装饰的函数
    time.sleep(0.01)
    print('老板好同事好大家好',a,b)
    return '新年好'
# func = timmer(func)
ret = func(1,2)   #inner()
ret = func(1,b = 2)   #inner()
print(ret)

#####
老板好同事好大家好 1 2
0.030028820037841797
老板好同事好大家好 1 2
0.010994195938110352
新年好

4)装饰器的固定格式

def wrapper(f):    #装饰器函数
    def inner(*args,**kwargs):
        '''被装饰函数之前加的内容'''
        ret = f(*args,**kwargs) #被装饰的函数
        '''被装饰函数之后加的内容'''
        return ret
    return inner

@wrapper         #语法糖 @装饰器函数名
def func():     #被装饰的函数
    time.sleep(0.01)
    print('老板好同事好大家好')
    return '新年好'

ret = func()
#温故而知新
def wrapper(func):
    def inner(*args,**kwargs): #接收参数时将参数聚合 inner((3))
        print("在被装饰函数之前加的内容")
        ret = func(*args,**kwargs)#调用函数时将参数打散 holiday(*(3),**{})
        print("在被装饰函数之后加的内容")
        return ret
    return inner
@wrapper # holidy = wrapper(holiday)
def holiday(day):
    print("全体放假%d天" %day)
    return "Happy!"
ret = holiday(3) #inner(3)print(ret)

####
在被装饰函数之前加的内容
全体放假3天
在被装饰函数之后加的内容
Happy!

5) wraps

def span():
    '''打印一个字符串的函数
    ::return:
    '''
    print("Python_Test!")
print(span.__name__) # 查看字符串格式的函数名
print(span.__doc__) # document

#######
span
打印一个字符串的函数
    ::return:

##################################################
from
functools import wraps #导入wraps装饰器 def wrapper(func): #func = holiday @wraps(func) def inner(*args,**kwargs): print('在被装饰的函数执行之前做的事') ret = func(*args,**kwargs) print('在被装饰的函数执行之后做的事') return ret return inner @wrapper #holiday = wrapper(holiday) def holiday(day): '''这是一个放假通知''' print('全体放假%s天'%day) return '好开心' print(holiday.__name__) #查看字符串格式的函数名 print(holiday.__doc__) #document ret = holiday(3) #inner print(ret)

###

holiday
这是一个放假通知
在被装饰的函数执行之前做的事
全体放假3天
在被装饰的函数执行之后做的事
好开心

###################################################

 ###三层装饰器

import time
FLAG = False                #定义全局变量
def timmer_out(flag):
    def timmer(func):
        def inner(*args,**kwargs):
            if flag:
                start = time.time()
                ret = func(*args,**kwargs)
                end = time.time()
                print(end-start)
                return ret
            else:
                ret = func(*args, **kwargs)
                return ret
        return inner
    return timmer
# timmer = timmer_out(FLAG)
@timmer_out(FLAG)    #wahaha = timmer(wahaha)
def wahaha():
    time.sleep(0.1)
    print('wahahahahahaha')

@timmer_out(FLAG)
def erguotou():
    time.sleep(0.1)
    print('erguotoutoutou')

wahaha()
erguotou()

 ##温故而知新(带参数的装饰器)

import time
FLAG = True
def timmer_out(flag):
    def timmer(func):
        def inner(*args,**kwargs):
            if flag:
                start = time.time()
                ret = func(*args,**kwargs)
                end = time.time()
                print(end-start)
                return ret
            else:
                ret = func(*args,**kwargs)
                return ret
        return inner
    return timmer
@timmer_out(FLAG)
def func1():
    time.sleep(0.1)
    print("Happy1111")
    return "呵呵呵!!!"

@timmer_out(FLAG)
def func2():
    time.sleep(0.1)
    print("Happy2222")
    return "哈哈哈!!!"

func1()
func2()

#####
Happy1111
0.10094833374023438
Happy2222
0.1000070571899414

 6)多个装饰器装饰同一个函数

def wrapper3(func):
    def inner3():
        print("In wrapper3 ,before func")
        ret = func()
        print("In wrapper3 ,after func")
        return ret
    return inner3

@wrapper3
@wrapper2
@wrapper1
def f():
    print("This is a f")
    return "万能装饰器!"

print(f())

###########
In wrapper3 ,before func
In wrapper2 ,before func
In wrapper1 ,before func
This is a f
In wrapper1 ,after func
In wrapper2 ,after func
In wrapper3 ,after func
万能装饰器!
 
原文地址:https://www.cnblogs.com/shaopan/p/10003966.html