内置方法 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 框架以及有大量细粒度行为的库时有奇效。

原文地址:https://www.cnblogs.com/CNHK1949/p/10645017.html

时间: 2024-10-27 07:06:50

内置方法 call enter exit的相关文章

Python类的内置方法

目录 1.new.init 2.str.repr 3.call 4.del 5.iter.next 6.getitem.setitem.delitem 7.getattr.setattr.delattr 8.getatrribute 9.enter.exit 10.get.set.delete.描述符(研究中,待补充) **(为了方便和美观,省略了各内置方法前后的__双下划线)** 1.new.init __new__方法是真正的类构造方法,用于产生实例化对象(空属性).重写__new__方法可

2017/9/11——何某某更博,花时间整理了所有的Python内置方法的用法,便于日后复习

1.这里是所有的内置方法的使用方法 # -*- coding:utf-8 -*- # Author : 何子辰 # 所有的内置方法总结 print('1.abs'.center(50,'*')) # abs 绝对值 a = abs(-5) print(a) print('2.all'.center(50,'*')) # all # Return True if all elements of the # iterable are true(or if the iterable # is empt

Python的内置方法和类的继承举例

1.类的内置方法 Python内部类:所谓内部类,就是在类的内部定义的类,主要目的是为了更好的抽象现实世界.例子:汽车是一个类,汽车的底盘轮胎也可以抽象为类,将其定义到汽车内中,而形成内部类,更好的描述汽车类,因为底盘轮胎是汽车的一部分.内部类实例化方法: 方法1:直接使用外部类调用内部类方法2:先对外部类进行实例化,然后再实例化内部类out_name = outclass_name()in_name = out_name.inclass_name()in_name.method() #!/us

面向对象-反射-其他内置方法

1.反射 1.1反射含义 通过字符串的形式操作对象的相关属性.方法有hasattr,getattr,delattr #!/usr/bin/env python # -*- coding:utf-8 -*- # Author: vita class People: country='China' def __init__(self,name,age): self.name=name self.age=age def talk(self): print('%s is talking' %self.n

Python中类的内置方法与继承关系实例

1.类的内置方法 Python内部类:所谓内部类,就是在类的内部定义的类,主要目的是为了更好的抽象现实世界.例子:汽车是一个类,汽车的底盘轮胎也可以抽象为类,将其定义到汽车内中,而形成内部类,更好的描述汽车类,因为底盘轮胎是汽车的一部分. 内部类实例化方法: 方法1:直接使用外部类调用内部类方法2:先对外部类进行实例化,然后再实例化内部类 out_name = outclass_name() in_name = out_name.inclass_name() in_name.method() #

issubclass和isinstance,反射,内置方法

目录 面向对象进阶 一.issubclass 和 isinstance 1.1 issubclass 1.2 isinstance 二.反射 2.1 什么是反射 2.2 四个可以通过字符串操作对象属性和方法的内置函数 2.2.1 hasattr() 2.2.2 getattr() 2.2.3 setattr() 2.3.4 delattr() 三.内置方法 3.1 __str__和__repr__ 3.2 点拦截方法:__setattr__,__delattr__,__getattr__ 3.3

实现纸牌游戏的随机抽牌洗牌过程(item系列几个内置方法的实例)

1.namedtuple:命名元组,可以创建一个没有方法只有属性的类 from collections import namedtuple card = namedtuple('card',['rank','suit']) # rank 牌面大小,suit牌面的花色 # card其实就是namedtuple创建的一个类,其属性就是rank和suit c1 = card(2,'红心 ') # c1是实例化的对象 print(c1) print(c1.suit) 运行结果: card(rank=2,

Python之基本数据类型及内置方法

Python之基本数据类型及内置方法 数字类型 整型 1.作用 年龄/id 2.定义方式 x = 10 3.使用方法 + - * / % // ** < <= > >= == != 4.有序or无序 有索引的就有序,无索引的就无序 压根就没有有序无序一说 5. 可变or不可变 值变id不变叫可变,值不变id变叫不可变 整型不可变 x = 10 print(id(x)) x += 1 print(id(x)) 浮点型 1.作用 薪资 2.定义方式 x = 10.1 3.使用方法 +

python开发函数进阶:命名空间,作用域,函数的本质,闭包,内置方法(globales)

一,命名空间 #局部命名空间#全局命名空间#内置命名空间 #三者的顺序#加载顺序 硬盘上--内存里#内置-->全局(从上到下顺序加载进来的)-->局部(调用的时候加载) 1 #!/usr/bin/env python 2 #_*_coding:utf-8_*_ 3 4 #全局命名空间 5 a = 5 6 b = 8 7 #局部命名空间(函数) 8 def my_max(): 9 c = a if a > b else b 10 return c 11 m = my_max() 12 pr