zoukankan      html  css  js  c++  java
  • 内置方法 call enter exit

    class A(object):
        def __init__(self,name,age):
            self.name = name
            self.age = age
        def __call__(self)
            print('AAA')
    A()()

    # 源码里用比较多 Flask web框架
    # 对象()自动触发__call__中的内容

    Python 的 __call__ 方法可以让类的实例具有类似于函数的行为,通常用于定义和初始化一些带有上下文的函数。

    既然说是妙处,那不得不提及 Python 世界中的那几个经典实现了。

    一个例子来源于 bottle 框架源码的 cached_property(被我改动了一些细节,但用法基本是一样的),为了在逻辑上构成一个封闭的整体,我们把一个实例当作函数来使用:

    class CachedProperty(object):
        _cache = {}
     
        def __call__(self, fn):
            @property
            @functools.wraps(fn)
            def wrapped(self):
                k = '%s:%s' % (id(self), fn.__name__)
                v = CachedProperty._cache.get(k)
                if v is None:
                    v = fn(self)
                    CachedProperty._cache[k] = v
                return v
     
            return wrapped
     
    cached_property = CachedProperty()

    使用的时候可以直接替换掉内置的 property 来缓存动态属性:

    class DB(object):
        def __init__(self, ...):
            ....
            
        @cached_property
        def conn(self):
            return create_connection(...)
            
    db = DB()
    db.conn # 创建连接并缓存

    还有个更复杂但非常实用的例子,Pipline,把函数封装成支持管道操作的运算过程:

    class Pipe(object):
        def __init__(self, fn):
            self.fn = fn
     
        def __ror__(self, other):
            return self.fn(other)
     
        def __call__(self, *args, **kwargs):
            op = Pipe(lambda x: self.fn(x, *args, **kwargs))
            return op

    可以像这样调用:

    @Pipe
    def sort(data, cmp=None, key=None, reverse=False):
        return sorted(data, cmp=cmp, key=None, reverse=reverse)
        
    [{'score': 1}, {'score': 3}, {'score': 2}] | sort(key=lambda x: x['score'])

    可以看出,类 Pipe 被当作一个装饰器使用,所以 sort 函数的原始定义被传递给 Pipe.__init__,构造出一个 Pipe 实例,所以被装饰过的 sort 函数,也就是我们后面使用的那个,实际上是一个 Pipe 类的实例,只是因为它有 __call__方法,所以可以作为函数来使用。

    这种用法在写一些 ORM 框架以及有大量细粒度行为的库时有奇效。

  • 相关阅读:
    如何将Superset嵌入后台系统之实践
    如何将Superset嵌入后台系统之实践
    SQL server添加链接服务器脚本
    面试题:JQuery有几种选择器?
    数据库增加索引
    Mybatis与Ibatis比较
    jQuery 选择器
    Form 和 Input 对象
    xgqfrms™, xgqfrms® : xgqfrms's offical website of GitHub!
    xgqfrms™, xgqfrms® : xgqfrms's offical website of GitHub!
  • 原文地址:https://www.cnblogs.com/CNHK1949/p/10645017.html
Copyright © 2011-2022 走看看