【问题标题】:overwrite file reference variable in with statement在 with 语句中覆盖文件引用变量
【发布时间】:2012-07-16 19:38:40
【问题描述】:

我很好奇这是否会导致任何不良行为。我运行了一个测试用例并且没有错误,所以我认为它没问题(尽管可能不是好的做法)。只是想知道 python 如何处理我认为应该存在的问题?

with open("somefile.txt","r") as fileinfo:
    fileinfo = fileinfo.readlines()

print fileinfo

我认为覆盖“fileinfo”会导致退出 with 语句的问题(引发一些关于无法 .close() 列表的错误)。 with 语句是否保留文件引用的本地副本?谢谢!

【问题讨论】:

  • @Levon 我不这样做。我只是想知道 python 如何解决这个问题。只是为了学习而学习
  • 啊 .. 好吧,很公平 .. 我想这是一个范围界定类型的问题,with

标签: python scope with-statement


【解决方案1】:

当然,Python 保留了对with 语句中使用的对象的内部引用。不然不使用as子句怎么办?

【讨论】:

  • 很好。促使我研究上下文管理器(以前我没有发现它)。
【解决方案2】:

with 语句确实存储了对文件对象的本地引用(尽管我不确定 self.gen 中存储的确切内容)

查看了该主题,特别是研究了上下文管理器,发现它为感兴趣的人提供了更多细节。

class GeneratorContextManager(object):
    def __init__(self, gen):
        # Store local copy of "file reference"
        self.gen = gen

        def __enter__(self):
            try:
                return self.gen.next()
            except StopIteration:
                raise RuntimeError("generator didn't yield")

        def __exit__(self, type, value, traceback):
            if type is None:
                try:
                    self.gen.next()
                except StopIteration:
                    return
                else:
                    raise RuntimeError("generator didn't stop")
            else:
                try:
                    self.gen.throw(type, value, traceback)
                    raise RuntimeError("generator didn't stop after throw()")
                except StopIteration:
                    return True
                except:
                    # only re-raise if it's *not* the exception that was
                    # passed to throw(), because __exit__() must not raise
                    # an exception unless __exit__() itself failed.  But
                    # throw() has to raise the exception to signal
                    # propagation, so this fixes the impedance mismatch 
                    # between the throw() protocol and the __exit__()
                    # protocol.
                    #
                    if sys.exc_info()[1] is not value:
                        raise

def contextmanager(func):
    def helper(*args, **kwds):
        return GeneratorContextManager(func(*args, **kwds))
           return helper

【讨论】:

    猜你喜欢
    • 2022-07-01
    • 2020-12-19
    • 2010-10-27
    • 2020-11-09
    • 1970-01-01
    • 1970-01-01
    • 2015-04-23
    相关资源
    最近更新 更多