内置方法 call enter exit

Posted cnhk1949

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了内置方法 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 框架以及有大量细粒度行为的库时有奇效。

以上是关于内置方法 call enter exit的主要内容,如果未能解决你的问题,请参考以下文章

Python类的内置方法

__enter__,__exit__

上下文管理器__enter__和__exit__

实现文件上下文管理(\_\_enter\_\_和\_\_exit\_\_)

Python进阶-----上下文管理协议(__enter__,__exit)

Python概念-上下文管理协议中的__enter__和__exit__