Python __call__() 语法
__call__() 是 Python 的一个特殊方法(又称 “魔法方法” 或 “双下划线方法”),它允许一个类的实例像函数一样被调用。
也就是说,如果一个类实现了 __call__() 方法,那么它的实例就成为了可调用对象。
语法:
class MyObject:
def __call__(self, *args, **kwargs):
# 实例被调用时的实现
return value
说明:
__call__() 方法除了 self(实例本身)之外,可以接收任意数量的位置参数 (*args) 和关键字参数 (**kwargs),就像普通函数一样。
self(必选):约定俗成的名称,表示实例对象。*args(可选):一个元组,包含所有传递给实例的位置参数。**kwargs(可选):一个字典,包含所有传递给实例的关键字参数。
__call__() 方法的返回值可以是任何类型,取决于其实现的逻辑。
对于 __call__() 方法来说,它常用于实现:
- 函数对象(Function Objects)或函子(Functors):封装状态的函数,每次调用都能利用这些状态。
- 装饰器(Decorators):当装饰器类被实例化并用于修饰函数时。
- 类工厂(Class Factories):根据不同参数创建或返回不同类型的实例。
- 具有定制行为的对象:例如,一个配置对象,可以通过调用来触发更新或返回特定配置。
Python __call__() 摘要
| 属于 | Python 魔法方法 |
|---|---|
| 使用频率 | 中 |
| 官方文档 | 查看 |
| 相关函数 | callable() |
Python __call__() 示例
接下来,我们通过几个简单的例子来讲解一下 Python __call__() 方法是如何使用的。
示例 1:__call__() 使对象变得可调用
class Greeter:
def __init__(self, greeting):
self.greeting = greeting
def __call__(self, name):
return f'{self.greeting}, {name}!'
# 创建 Greeter 实例
greeter = Greeter('Hello')
# 像函数一样调用实例
print(greeter('Jack'))
# 检查对象是否可调用
print(callable(greeter))
运行结果如下。
Hello, Jack!
True
分析:
在这个例子中,我们定义了一个名为 “Greeter” 的类,并在其内部实现了 __call__() 方法。因此 Greeter 类的实例 greeter 会变得可调用。
也就是说,我们可以像调用函数一样来调用 greeter()。当 Greeter('Hello') 被调用时,实际上就触发了 greeter 实例的 __call__() 方法。
此外,我们还可以使用 callable() 函数来判断一个对象是否实现了 __call__() 方法。
示例 2:__call__() 作为状态机或计数器
class Counter:
def __init__(self, initial_value=0):
self.count = initial_value
def __call__(self):
self.count += 1
return self.count
# 创建计数器实例
first_counter = Counter()
# 每次调用实例,计数器值增加
print(first_counter()) # 1
print(first_counter()) # 2
print(first_counter()) # 3
another_counter = Counter(10)
print(another_counter()) # 11
print(another_counter()) # 12
运行结果如下。
1
2
3
11
12
分析:
在这个例子中,Counter 类的实例充当了一个简单的计数器。每次调用 my_counter(),它内部的 count 属性就会递增,并返回当前值。
示例 3:__call__() 用于实现装饰器
class MyDecorator:
def __init__(self, fn):
self.fn = fn
def __call__(self, *args, **kwargs):
print('在函数调用之前执行一些操作...')
result = self.fn(*args, **kwargs)
print('在函数调用之后执行一些操作...')
return result
@MyDecorator
def hello(name):
print(f'Hello, {name}!')
return f'Result for {name}'
@MyDecorator
def add(a, b):
print(f'Calculating {a} + {b}...')
return a + b
hello('Jack')
result = add(10, 20)
print(result)
运行结果如下。
在函数调用之前执行一些操作...
Hello, Jack!
在函数调用之后执行一些操作...
在函数调用之前执行一些操作...
Calculating 10 + 20...
在函数调用之后执行一些操作...
30
分析:
MyDecorator 是一个 装饰器。当 hello() 函数被 @MyDecorator 装饰时,hello() 函数本身会被作为参数传递给 MyDecorator 的 __init__() 方法,并创建一个 MyDecorator 的实例。
然后,每当调用 hello 时,实际上就是调用了 MyDecorator 实例的 __call__() 方法,该方法在执行原始函数前后添加了额外的逻辑。
示例 4:带有参数的 __call__()
class Calculator:
def __call__(self, operation, a, b):
if operation == 'add':
return a + b
elif operation == 'subtract':
return a - b
else:
raise ValueError('不支持的操作')
# 创建计算器实例
calc = Calculator()
# 像函数一样调用实例,并传递参数
print(calc("add", 20, 10))
print(calc("subtract", 20, 10))
try:
print(calc('multiply', 4, 8))
except ValueError as e:
print(e)
运行结果如下。
30
10
不支持的操作
分析:
__call__() 方法可以像一个普通函数一样接收不同的参数。Calculator 实例被调用时,根据传入的 operation 参数执行不同的计算。这样可以使得一个对象能够封装多种不同行为,并以统一的函数调用方式来对外暴露。
