我已经阅读了 FastAPI 关于中间件的文档(特别是中间件教程、CORS 中间件部分和高级中间件指南),但找不到如何编写可以使用该add_middleware函数添加的中间件类的具体示例(相反到使用装饰器添加的基本中间件功能),也不在此站点上。
我更喜欢使用add_middleware基于应用程序的装饰器的原因是,我想在共享库中编写一个中间件,该库将由多个不同的项目使用,因此我无法将其绑定到特定实例FastAPI。
所以我的问题是:你是如何做到的?
在这个相关问题之后,虽然总是有一些库以独特的方式使用语言功能的例子,但我想知道返回方法以外的值是否self应该__enter__被视为反模式。
在我看来,这似乎是一个坏主意的主要原因是它使包装上下文管理器出现问题。例如,在 Java 中(也可能在 C# 中),可以将一个AutoCloseable类包装在另一个类中,该类将负责内部类之后的清理工作,如以下代码片段所示:
try (BufferedReader reader =
new BufferedReader(new FileReader("src/main/resources/input.txt"))) {
return readAllLines(reader);
}
Run Code Online (Sandbox Code Playgroud)
在这里,BufferedReader包装FileReader,并在其自己的方法中调用FileReader的方法。但是,如果这是 Python,并且会在其方法中返回 self 以外的对象,则这将使这种安排变得更加复杂。作者必须解决以下问题:close()close()FileReader__enter__BufferedReader
FileReader自己的方法时,是FileReader直接使用还是使用其方法返回的对象__enter__?返回的对象甚至支持哪些方法?__exit__方法中,我需要仅关闭FileReader对象,还是方法中返回的对象__enter__?__enter__如果在调用时实际上返回一个不同的对象,会发生什么?我现在是否需要保留它返回的所有不同对象的集合,以防有人__enter__多次调用我?当我需要使用这些对象时,我如何知道使用哪一个?而这样的例子不胜枚举。解决所有这些问题的一种半成功的解决方案是简单地避免一个上下文管理器类在另一个上下文管理器类之后进行清理。在我的示例中,这意味着我们需要两个嵌套with块 - 一个用于FileReader,另一个用于BufferedReader。然而,这使得我们编写更多的样板代码,并且看起来明显不太优雅。
总而言之,这些问题让我相信,虽然 Python 确实允许我们返回方法self中以外的内容__enter__,但这种行为应该避免。对于这些问题有官方或半官方的表态吗?负责任的 Python 开发人员应该如何编写解决这些问题的代码?
一些地方在网上,其中包括堆栈溢出的答案(如这个,这个和这个),提到了Python迭代器必须实现的__next__方法(我的理解)和该__iter__方法。这些地方正确地得出结论,所有迭代器也是可迭代的。如果注释为 a 的变量typing.Iterator未实现该__iter__方法,则即使 PyCharm 也会发出类型警告。
与这些相反,关于迭代器的官方 Python 教程部分只提到需要一个__next__方法:
该函数返回一个迭代器对象,该对象定义了
__next__()一次访问容器中元素的方法
所以我的问题是:Python 迭代器是否正式需要自己成为可迭代对象?我个人不明白为什么这应该是真的,以及为什么我们不能完全分离 anIterable和 an的要求Iterator。