10 带参数的装饰器 通用装饰器 类装饰器

版本1)不带参数的闭包

def timefun(func):
    print('---fun1--')    
    def time_in():
        print("--time_in is 1")
        func()
        print('---time_in is 2')

    print('---fun2--')    
    return time_in

def f1():
    print("this is f1")

f1 = timefun(f1)

f1()
---fun1--
---fun2--
--time_in is 1
this is f1
---time_in is 2

版本2)不带参数函数的被装饰

def timefun(func):
    print('---fun1--')    
    def time_in():
        print("--time_in is 1")
        func()
        print('---time_in is 2')

    print('---fun2--')    
    return time_in

@timefun
def f1():
    print("this is f1")

f1()

版本3)带参数函数的被装饰

def timefun(func):
    print('---fun1--')    
    def time_in(num1,num2):
        print("--time_in is 1")
        func(num1,num2)
        print('---time_in is 2')

    print('---fun2--')    
    return time_in

@timefun
def f1(a,b):
    print('--f1:a=%d,b=%d'%(a,b))

f1(1,2)

版本4)不定长参数函数被装饰

def timefun(func):
    print('---装饰用的1--')    
    def time_in(*args,**kwargs):
        print("--time_in is 1")
        func(*args,**kwargs)
        print('---time_in is 2')

    print('---fun2--')    
    return time_in

@timefun
def f1(a,b):
    print('--f1:a=%d,b=%d'%(a,b))

@timefun
def f2(a,b,c,d):
    print('--f2:a=%d,b=%d,c=%d,d=%d'%(a,b,c,d))

f1(1,2)
f2(1,2,3,4)

5  带返回值的函数 被装饰

  1)带返回值的函数

 
 def test():
     print('----test--')
     return "haha"
 
 ret = test()
 print("test return ---%s"%ret)



## 运行结果
----test--
test return ---haha

  

  2)带返回值的装饰器

def fun(func):
    
    def time_in():
        func()
    return time_in

@fun
def test():
    print('----test--')
    return "haha"

ret = test()
print("test return ---%s"%ret)


### 运行结果
----test--
test return ---None

  

  3)带返回值的函数 被装饰

def fun(func):
    
    def time_in():
        ret = func()  #保存返回来的haha
        return ret   #把haha返回到最后17行的调用
    return time_in 

@fun
def test():
    print('----test--')
    return "haha"

ret = test()
print("test return ---%s"%ret)

6.通用装饰器

def func(func):

    def fun_in(*args,**kwargs):
        print('--记录日志--')
        re = func(*args,**kwargs)
        return re
    return fun_in

@func
def test1():
    print('--test1')
    return "haha"

@func
def test2():
    print('--test2--a=%d')
    
@func
def test3(a):
    print('--test3--a=%d'%a)

ret = test1()
print('test return :%s'%ret)

ret2 = test2()
print('test2 return :%s'%ret2)

test3(11)
--记录日志--
--test1
test return :haha
--记录日志--
--test2--a=%d
test2 return :None
--记录日志--
--test3--a=11

7.装饰器带参数,

在原有装饰器的基础上,设置外部变量,执行一次函数,获取它的返回值而已

def func_arg(arg):
    def func(functionName):
        
        def func_in():
            print("---记录日志-%s-"%arg)
            functionName()
        return func_in
    return func
#1.先执行func_arg("heihei")函数,这个函数return 的结果是func这个函数的引用
#2.@func
#3.使用@func对test进行装饰
@func_arg('heihei')
def test1():
    print('---testt')

test1()
---记录日志-heihei-
---testt

2)有什么用

def func_arg(arg):
    def func(functionName):
        
        def func_in():
            print("---记录日志-%s-"%arg)
            if arg == "alex":
                functionName()
                functionName()
            else:
                functionName()
        return func_in
    return func
#1.先执行func_arg("heihei")函数,这个函数return 的结果是func这个函数的引用
#2.@func
#3.使用@func对test进行装饰
@func_arg('heihei')
def test1():
    print('---testt')

#带有参数的装饰器,能够起到在运行时,有不同的功能
@func_arg('alex')
def test2():
    print('---alex')

test1()
test2()
---记录日志-heihei-
---testt
---记录日志-alex-
---alex
---alex

8.类装饰器__call__

  1 __call__方法

装饰器函数其实是这样一个接口约束,它必须接受一个callable对象作为参数,然后返回一个callable对象。在Python中一般callable对象都是函数,但也有例外。只要某个对象重写了 __call__() 方法,那么这个对象就是callable的。

In [18]: class Dog(object):
   ....:     def __call__(self):
   ....:         print("---test-")
   ....:         

In [19]: d = Dog()

In [20]: d()
---test-

  2)类装饰器

class Test(object):
    def __init__(self, func):
        print("---初始化---")
        print("func name is %s"%func.__name__)
        self.__func = func
    def __call__(self):
        print("---装饰器中的功能---")
        self.__func()
#说明:
#1. 当用Test来装作装饰器对test函数进行装饰的时候,首先会创建Test的实例对象
#    并且会把test这个函数名当做参数传递到__init__方法中
#    即在__init__方法中的func变量指向了test函数体
#
#2. test函数相当于指向了用Test创建出来的实例对象
#
#3. 当在使用test()进行调用时,就相当于让这个对象(),因此会调用这个对象的__call__方法
#
#4. 为了能够在__call__方法中调用原来test指向的函数体,所以在__init__方法中就需要一个实例属性来保存这个函数体的引用
#    所以才有了self.__func = func这句代码,从而在调用__call__方法中能够调用到test之前的函数体
@Test
def test():
    print("----test---")
test()
showpy()#如果把这句话注释,重新运行程序,依然会看到"--初始化--"
运行结果如下:

---初始化---
func name is test
---装饰器中的功能---
----test---

    

    

原文地址:https://www.cnblogs.com/venicid/p/7929427.html