• python装饰器系列(六)


    可调用对象

    在python中可以用callable函数查看一个对象是不是可调用

    1 def fn():
    2     print('ha ha ha')
    1 callable(fn)
    2 True

    输出为True,函数当然是一个可调用对象,如果是一个类呢?

    1 class Fun:
    2     def __init__(self,name):
    3         self.name = name
    4 
    5 f = Fun('zhaochj')
    1 callable(f)
    2 False

    如上,一个类被实例化后,这个实例对象是一个不可调用对象

    有什么方法能让一个实例对象变成可调用对象呢?做如下修改:

    1 class Fun_1:
    2     def __init__(self,name):
    3         self.name = name
    4         
    5     def __call__(self):
    6         print('my name is {0}'.format(self.name))
    1 f1 = Fun_1('zhaochj')
    2 
    3 callable(f1)
    4 True

    f1这个实例现在已是一个可调用对象了。所以只要一个类中实现了__call__方法,那么类实例就是一个可调用对象

    1 f1()
    2 my name is zhaochj

    事实证明,调用此实例对象也就是执行了__call__方法。既然是可调用对象,就可以向调用函数一样传递参数来调用,只要在__call__方法中定义可接收参数即可。

    类通过实现__call__方法可以让实例变成一个可调用对象,如果我们向这个可调用对象传递一个函数作为其参数,那__call__函数就可以写成一个装饰器

     1 import functools
     2 class InjectUser:
     3     def __init__(self,default_user):
     4         self.user = default_user
     5         
     6     def __call__(self,fn):
     7         @functools.wraps(fn)
     8         def wrap(*args,**kwargs):
     9             if 'user' not in kwargs.keys():
    10                 kwargs['user'] = self.user
    11             return fn(*args,**kwargs)
    12         return wrap
    1 @InjectUser('zhaochj')
    2 def do_somthings(*args,**kwargs):
    3     print(kwargs.get('user'))
    1 do_somthings()
    2 zhaochj

    对上述的代码进行分析:

    1 def __call__(self,fn):
    2         @functools.wraps(fn)
    3         def wrap(*args,**kwargs):
    4             if 'user' not in kwargs.keys():
    5                 kwargs['user'] = self.user
    6             return fn(*args,**kwargs)
    7         return wrap

    上边的代码是定义一个装饰器

    1 @InjectUser('zhaochj')
    2 def do_somthings(*args,**kwargs):
    3     print(kwargs.get('user'))

    这里的魔法等价执行了InjectUser('zhaochj')(do_somthings),实质是返回装饰器的wrap函数。执行do_somthings()时,实质是执行了wrap(),并返回fn(*args,**kwargs),到这里才真正执行函数中的print语句

    1 def do_somthings(*args,**kwargs):
    2     print(kwargs.get('user'))
  • 相关阅读:
    重学Java 面向对象 之 final
    java并发学习04---Future模式
    java并发学习03---CountDownLatch 和 CyclicBarrier
    java并发学习02---ReadWriteLock 读写锁
    java并发学习01 --- Reentrantlock 和 Condition
    链表的倒数第k个节点
    重建二叉树
    java并发学习--线程池(一)
    二叉树的深度
    vue-常用指令(v-for)
  • 原文地址:https://www.cnblogs.com/tianshug/p/10922051.html
Copyright © 2020-2023  润新知