- html - 出于某种原因,IE8 对我的 Sass 文件中继承的 html5 CSS 不友好?
- JMeter 在响应断言中使用 span 标签的问题
- html - 在 :hover and :active? 上具有不同效果的 CSS 动画
- html - 相对于居中的 html 内容固定的 CSS 重复背景?
关注 this related question ,虽然总是有一些库以独特的方式使用语言特性的例子,但我想知道是否返回 self
以外的值在 __enter__
方法应该被认为是一种反模式。
这在我看来是个坏主意的主要原因是它使包装上下文管理器成为问题。例如,在 Java 中(也可能在 C# 中),可以包装一个 AutoCloseable
另一个类中的类,它将在内部类之后进行清理,例如以下代码片段:
try (BufferedReader reader =
new BufferedReader(new FileReader("src/main/resources/input.txt"))) {
return readAllLines(reader);
}
BufferedReader
包裹
FileReader
, 并调用
FileReader
的
close()
自己的方法
close()
方法。但是,如果这是 Python,并且
FileReader
会在其
__enter__
中返回除 self 以外的对象方法,这将使这样的安排更加复杂。
BufferedReader
的作者必须解决以下问题:
FileReader
对于我自己的方法,我是否使用 FileReader
直接或其__enter__
返回的对象方法?返回的对象甚至支持哪些方法? __exit__
方法,我是否只需要关闭 FileReader
对象,或 __enter__
中返回的对象方法? __enter__
会发生什么?实际上在调用时返回了一个不同的对象?我现在是否需要保留它返回的所有不同对象的集合,以防有人调用 __enter__
几次对我?当我需要使用这些对象时,我如何知道使用哪一个? with
block - 一个用于
FileReader
, 一个用于
BufferedReader
.然而,这使我们编写了更多样板代码,并且看起来明显不那么优雅。
self
以外的东西。在
__enter__
方法,应该简单地避免这种行为。关于这些问题是否有一些官方或半官方的评论?一个负责任的 Python 开发人员应该如何编写代码来解决这些问题?
最佳答案
TLDR:返回 self
以外的其他内容来自 __enter__
非常好,也不错。
introducing PEP 343和 Context Manager specification明确将此列为所需的用例。
An example of a context manager that returns a related object is the one returned by
decimal.localcontext()
. These managers set the active decimal context to a copy of the original decimal context and then return the copy. This allows changes to be made to the current decimal context in the body of thewith
statement without affecting code outside thewith
statement.
self
以外的内容的示例。来自
__enter__
.值得注意的是,
contextlib
的大部分内容匹配这个模式。
contextlib.contextmanager
生成无法返回 self
的上下文管理器,因为没有这样的东西。 contextlib.closing
包裹 thing
并返回 __enter__
. contextlib.nullcontext
返回一个预定义的常量 threading.Lock
返回 bool 值 decimal.localcontext
返回其参数的副本 __enter__
的返回值对协议(protocol)无关紧要 .
cm.__enter__
,它负责运行cm.__exit__
. 值得注意的是,任何代码都可以访问
cm
(上下文管理器本身);
cm.__enter__
的结果无需调用
cm.__exit__
.
ContextManager
的代码必须完全运行它。任何其他代码都不必关心它的值是否来自
ContextManager
或不。
# entering a context manager requires closing it…
def managing(cm: ContextManager):
value = cm.__enter__() # must clean up `cm` after this point
try:
yield from unmanaged(value)
except BaseException as exc:
if not cm.__exit__(type(exc), exc, exc.__traceback__):
raise
else:
cm.__exit__(None, None, None)
# …other code does not need to know where its values come from
def unmanaged(smth: Any):
yield smth
__enter__
,它必须调用它的
__exit__
也是。如果外部上下文管理器已经有进入的内部上下文管理器,它不负责清理。
self
实际上是不好的做法。来自
__enter__
.返回
self
来自
__enter__
只有在
self
时才应该这样做预先完全初始化;如果
__enter__
运行任何初始化代码,应返回一个单独的对象。
class BadContextManager:
"""
Anti Pattern: Context manager is in inconsistent state before ``__enter__``
"""
def __init__(self, path):
self.path = path
self._file = None # BAD: initialisation not complete
def read(self, n: int):
return self._file.read(n) # fails before the context is entered!
def __enter__(self) -> 'BadContextManager':
self._file = open(self.path)
return self # BAD: self was not valid before
def __exit__(self, exc_type, exc_val, tb):
self._file.close()
class GoodContext:
def __init__(self, path):
self.path = path
self._file = None # GOOD: Inconsistent state not visible/used
def __enter__(self) -> TextIO:
if self._file is not None:
raise RuntimeError(f'{self.__class__.__name__} is not re-entrant')
self._file = open(self.path)
return self._file # GOOD: value was not accessible before
def __exit__(self, exc_type, exc_val, tb):
self._file.close()
GoodContext
返回一个不同的对象,它仍然负责清理。另一个上下文管理器包装
GoodContext
不需要关闭返回值,只需要调用
GoodContext.__exit__
.
关于python - 在 `self` 中返回 `__enter__` 以外的值是反模式吗?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/60561959/
我需要将文本放在 中在一个 Div 中,在另一个 Div 中,在另一个 Div 中。所以这是它的样子: #document Change PIN
奇怪的事情发生了。 我有一个基本的 html 代码。 html,头部, body 。(因为我收到了一些反对票,这里是完整的代码) 这是我的CSS: html { backgroun
我正在尝试将 Assets 中的一组图像加载到 UICollectionview 中存在的 ImageView 中,但每当我运行应用程序时它都会显示错误。而且也没有显示图像。 我在ViewDidLoa
我需要根据带参数的 perl 脚本的输出更改一些环境变量。在 tcsh 中,我可以使用别名命令来评估 perl 脚本的输出。 tcsh: alias setsdk 'eval `/localhome/
我使用 Windows 身份验证创建了一个新的 Blazor(服务器端)应用程序,并使用 IIS Express 运行它。它将显示一条消息“Hello Domain\User!”来自右上方的以下 Ra
这是我的方法 void login(Event event);我想知道 Kotlin 中应该如何 最佳答案 在 Kotlin 中通配符运算符是 * 。它指示编译器它是未知的,但一旦知道,就不会有其他类
看下面的代码 for story in book if story.title.length < 140 - var story
我正在尝试用 C 语言学习字符串处理。我写了一个程序,它存储了一些音乐轨道,并帮助用户检查他/她想到的歌曲是否存在于存储的轨道中。这是通过要求用户输入一串字符来完成的。然后程序使用 strstr()
我正在学习 sscanf 并遇到如下格式字符串: sscanf("%[^:]:%[^*=]%*[*=]%n",a,b,&c); 我理解 %[^:] 部分意味着扫描直到遇到 ':' 并将其分配给 a。:
def char_check(x,y): if (str(x) in y or x.find(y) > -1) or (str(y) in x or y.find(x) > -1):
我有一种情况,我想将文本文件中的现有行包含到一个新 block 中。 line 1 line 2 line in block line 3 line 4 应该变成 line 1 line 2 line
我有一个新项目,我正在尝试设置 Django 调试工具栏。首先,我尝试了快速设置,它只涉及将 'debug_toolbar' 添加到我的已安装应用程序列表中。有了这个,当我转到我的根 URL 时,调试
在 Matlab 中,如果我有一个函数 f,例如签名是 f(a,b,c),我可以创建一个只有一个变量 b 的函数,它将使用固定的 a=a1 和 c=c1 调用 f: g = @(b) f(a1, b,
我不明白为什么 ForEach 中的元素之间有多余的垂直间距在 VStack 里面在 ScrollView 里面使用 GeometryReader 时渲染自定义水平分隔线。 Scrol
我想知道,是否有关于何时使用 session 和 cookie 的指南或最佳实践? 什么应该和什么不应该存储在其中?谢谢! 最佳答案 这些文档很好地了解了 session cookie 的安全问题以及
我在 scipy/numpy 中有一个 Nx3 矩阵,我想用它制作一个 3 维条形图,其中 X 轴和 Y 轴由矩阵的第一列和第二列的值、高度确定每个条形的 是矩阵中的第三列,条形的数量由 N 确定。
假设我用两种不同的方式初始化信号量 sem_init(&randomsem,0,1) sem_init(&randomsem,0,0) 现在, sem_wait(&randomsem) 在这两种情况下
我怀疑该值如何存储在“WORD”中,因为 PStr 包含实际输出。? 既然Pstr中存储的是小写到大写的字母,那么在printf中如何将其给出为“WORD”。有人可以吗?解释一下? #include
我有一个 3x3 数组: var my_array = [[0,1,2], [3,4,5], [6,7,8]]; 并想获得它的第一个 2
我意识到您可以使用如下方式轻松检查焦点: var hasFocus = true; $(window).blur(function(){ hasFocus = false; }); $(win
我是一名优秀的程序员,十分优秀!