【问题标题】:Python, check if called within 'with' statementPython,检查是否在'with'语句中调用
【发布时间】:2021-08-22 16:00:41
【问题描述】:

我正在实现我的自定义open() 函数(我们称之为myOpen())。任务是,我希望能够通过 with 语句 (with myOpen(...) as myFile:) 使用此功能。据我所知,open() 必须返回文件对象(TextIOBinaryIO)。但是open()with 语句的上下文中不是函数,而是实现__enter____exit__ 的类。你有什么想法,如何将这两件事结合在一起? 谢谢!

【问题讨论】:

  • 这篇文章解释了如何在 with 表达式中使用 __enter____exit__stackoverflow.com/questions/1984325/…
  • 当你使用with x() as y时,它实际上是在分配y = x().__enter__()
  • @Peter 调用with x() as y,其中x() 是函数,正在给我AttributeError: __enter__(Python 3.9.5)
  • 啊,nvm,我重读了这个问题,答案是否定的,你不能将上下文管理器和函数结合起来,一次做两件事。但是,您可以做的是以在__init__ 中完成逻辑并且只有def __enter__(self): return self 的方式设计一个类。这样,无论是否使用with,您都可以获得相同的结果。

标签: python with-statement


【解决方案1】:

嗯,我知道问题出在哪里了。一开始我想,with 语句只能在类上调用,它具有那些神奇的方法(__enter____exit__)。所以:

with class_that_has_those_methods as return_value_from_enter:
    pass

但它的工作方式不同。 with 之后的表达式也可以是函数,但它必须返回类的实例,它实现了那些神奇的方法。我认为,这也是 python 的open 的工作方式。它是函数,它返回文件对象(更准确地说是包装器):

>>> type(open)
<class 'builtin_function_or_method'>
>>> type(open('file', 'w'))
<class '_io.TextIOWrapper'>

该文件对象实现了这些神奇的方法:

>>> a = open('file', 'w')
>>> dir(a)
[... '__dir__', '__doc__', '__enter__', '__eq__', '__exit__', '__format__', ...]

所以要解决我原来的问题,myOpen() 必须是函数,它返回文件对象,具有 __enter____exit__ 方法。

【讨论】:

    【解决方案2】:

    使用with 语句仍会返回_io.x 类。

    >>> type(open('_file_'))
    <class '_io.TextIOWrapper'>
    >>> with open('_file_') as o: print(type(o))
    ... 
    <class '_io.TextIOWrapper'>
    

    with 语句只是为代码块分配另一个变量。 示例:

    def five():
        return 5
    
    print(five()) # -> 5
    print(type(five())) # -> int
    
    with five() as x:
        print(x) # -> 5
        print(type(x)) # -> int
    
    print(x) # -> 5
    

    with 语句等价于

    x = five()
    print(x)
    print(type(x))
    

    或者,对于FileIO

    handle = open('_file_')
    # do things with handle
    

    【讨论】:

    • 谢谢,好吧,with five() as x 给了我AttributeError: __enter__ (python 3.9.5)。另一个问题是如何处理myOpen() 中的__exit__?当with 语句存在时,如何关闭myOpen() 函数中的文件描述符?
    • 使用__enter____exit__ 方法为您的特殊文件句柄创建一个类。
    猜你喜欢
    • 2023-02-22
    • 2015-11-12
    • 1970-01-01
    • 1970-01-01
    • 2017-04-01
    • 2018-06-22
    • 1970-01-01
    • 1970-01-01
    • 2014-04-11
    相关资源
    最近更新 更多