在Python中,__init__
和 __call__
是两个特殊的方法,它们在类的上下文中有特定的用途:
-
__init__
方法:- 这是类的初始化方法,当一个实例被创建时,它会被自动调用。
- 它通常用于接收初始化参数并设置实例的初始状态。
- 在你的示例中,
FixedContentQueryChecker
类的__init__
方法接收一个参数fixed_content
,并将其存储在实例变量self.fixed_content
中。这个变量随后可以在类的其他方法中使用。
-
__call__
方法:- 当一个实例被用作函数时,
__call__
方法会被自动调用。 - 这意味着如果你有一个类的实例,并且你像调用函数一样调用这个实例(即
instance()
),Python 会寻找并执行__call__
方法。 - 在你的示例中,
__call__
方法定义了FixedContentQueryChecker
类的行为,使其可以像函数一样被调用。它接收一个参数q
,这是一个字符串,默认为空字符串。方法内部检查self.fixed_content
是否为q
的子串,如果是,则返回True
,否则返回False
。
- 当一个实例被用作函数时,
from typing import Annotated
from fastapi import Depends, FastAPI
app = FastAPI()
class FixedContentQueryChecker:
def __init__(self, fixed_content: str):
self.fixed_content = fixed_content
def __call__(self, q: str = ""):
if q:
return self.fixed_content in q
return False
checker = FixedContentQueryChecker("bar")
@app.get("/query-checker/")
async def read_query_check(fixed_content_included: Annotated[bool, Depends(checker)]):
return {"fixed_content_in_query": fixed_content_included}
在你的FastAPI应用示例中,FixedContentQueryChecker
类被用作一个依赖项,它检查查询参数中是否包含特定的固定内容。这里是详细步骤:
FixedContentQueryChecker
类被实例化为checker
,初始化时传入了字符串"bar"
。- 在FastAPI路由装饰器
@app.get("/query-checker/")
下,定义了一个异步视图函数read_query_check
。 - 这个视图函数使用了一个依赖项
Annotated[bool, Depends(checker)]
,它告诉FastAPI在调用视图函数之前,先调用checker
实例(即调用它的__call__
方法)。 - 依赖项的参数
q
默认为空字符串,但FastAPI会将查询参数q
的值传递给checker
实例。 checker
实例的__call__
方法检查传递给它的查询参数q
是否包含"bar"
字符串,并将结果作为fixed_content_included
参数传递给read_query_check
视图函数。- 视图函数返回一个字典,包含一个键
fixed_content_in_query
,其值是checker
实例检查的结果。
这样,当用户发送GET请求到 /query-checker/
并提供查询参数 q
时,FastAPI会调用 checker
实例来检查 q
是否包含 "bar"
,并将结果作为JSON响应返回。
补课:
在Python中,当你想让一个类的实例表现得像一个函数时,你可以在类定义中实现 __call__
方法。这个方法在实例被调用(使用圆括号 ()
)时自动触发。这使得对象可以采用类似函数的调用方式。
下面是一个简单的例子,演示如何使用 __call__
方法:
class Greeting:
def __init__(self, name):
self.name = name
def __call__(self):
return f"Hello, {self.name}!"
# 创建一个Greeting类的实例
greeter = Greeting("World")
# 调用这个实例,就像它是一个函数一样
print(greeter()) # 输出: Hello, World!
创建一个类的实例跟调用实例是不一样的。
在这个例子中,Greeting
类有一个 __init__
方法来初始化实例,接收一个名字 name
。__call__
方法则定义了当实例被调用时应该执行的操作,这里是返回一个问候语。
另一个例子:创建一个简单的计算器
让我们创建一个可以像函数一样调用的简单计算器类:
class Calculator:
def __init__(self, a=0, b=0):
self.a = a
self.b = b
def __call__(self, operation):
if operation == "add":
return self.a + self.b
elif operation == "subtract":
return self.a - self.b
elif operation == "multiply":
return self.a * self.b
elif operation == "divide":
if self.b != 0:
return self.a / self.b
else:
return "Error: Division by zero"
# 创建一个Calculator实例
calc = Calculator(10, 5)
# 调用实例来执行加法
print(calc("add")) # 输出: 15
# 调用实例来执行减法
print(calc("subtract")) # 输出: 5
# 调用实例来执行乘法
print(calc("multiply")) # 输出: 50
# 调用实例来执行除法
print(calc("divide")) # 输出: 2.0
# 尝试除以零
print(calc("divide")) # 输出: Error: Division by zero
在这个例子中,Calculator
类的 __call__
方法接收一个操作参数 operation
,根据传入的操作类型(加法、减法、乘法、除法),执行相应的运算。
通过实现 __call__
方法,类的实例可以被直接调用,这使得它们在某些情况下非常有用,特别是在需要自定义函数对象或实现回调函数时。