用户定义的可调用类型


用户定义的可调用类型

不仅Python函数是真正的对象,任何Python对象都可以表现得像函数。为此,只需要实现方法__call__

# 调用BingoCage实例,从打乱的列表中取出一个元素
import random

class BingoCage:
    def __init__(self, items):
        self._items = list(items)  # __init__接受任何可迭代对象:在本地构建一个副本,防止列表参数的意外副作用
        random.shuffle(self._items)  # 使用shuffle函数打乱列表self._items

    def pick(self):  # 随机取出列表中的数
        try:
            return self._items.pop()  #
        except IndexError:
            raise LookupError('pick from empty BingoCage')  # 如果列表为空,抛出异常,并设置错误信息

    def __call__(self):  # bingo.pick()的快捷方式是bingo()
        return self.pick()
bingo=BingoCage(range(3))
bingo.pick()
0
bingo()
2
callable(bingo)
True

实现__call__方法的类是创建函数类对象的简便方式,此时必须在内部维护一个状态,让它在调用之间可用,例如BingoCage中的剩余元素。装饰器就是这样。装饰器必须是函数,而且有时要在多次调用之间“记住”某些事(例如备忘(memorization),即缓存消耗较大的计算结果,供后面使用)。

创建保有内部状态的函数,还有一种截然不同的方式——使用闭包。