我正在使用Python 3.x.有人可以向我解释下面代码块中的file
是什么?
with open(filename, "a") as file:
file.write("Hello world")
print(file) #I added this line to try to understand what 'file' is.
当我运行上面的代码时,print(file)
产生了这个:
<_io.TextIOWrapper name='Class_A.txt' mode='a' encoding='cp1252'>
我不明白这一点。我可以看到它与with语句有关,但它看起来并不像变量。
那么file
是什么?它是变量还是别的什么?如果它是变量,它是什么数据类型?
答案 0 :(得分:4)
是的,file
是一个变量,引用open()
返回的上下文管理器生成的任何内容。它碰巧是同一个对象。换句话说,file
引用文件对象。
你也可以这样做,效果如下:
file = open(filename, "a")
try:
file.write("Hello world")
finally:
file.close()
因此文件会自动关闭。这是因为文件对象是上下文管理器;他们支持context manager protocol。从技术上讲,with context_manager as <name>
目标变量绑定到context_manager.__enter__()
的返回值,但文件对象从该方法返回自身,file.__exit__()
方法关闭文件。请参阅with
compound statement documentation。
现在,当您打印一个没有字符串表示的对象时,它将使用repr()
函数打印:
>>> repr(open('/dev/null'))
"<_io.TextIOWrapper name='/dev/null' mode='r' encoding='UTF-8'>"
>>> print(repr(open('/dev/null')))
<_io.TextIOWrapper name='/dev/null' mode='r' encoding='UTF-8'>
所以是的,这只是另一个对象,一个具有自定义,有用的表示。文件对象实现object.__repr__()
hook以产生这个:
>>> open('/dev/null').__repr__()
"<_io.TextIOWrapper name='/dev/null' mode='r' encoding='UTF-8'>"
文件对象的名称在这里也可能令人困惑。这是因为Python中的文件对象是io
module定义的一系列对象的一部分;一个TextIOWrapper
object包装一个缓冲区(这里是一个BufferedReader
,它将以FileIO
object的形式包装原始的二进制文件对象:
>>> devnull = open('/dev/null', 'r')
>>> devnull
<_io.TextIOWrapper name='/dev/null' mode='r' encoding='UTF-8'>
>>> devnull.buffer
<_io.BufferedReader name='/dev/null'>
>>> devnull.buffer.raw
<_io.FileIO name='/dev/null' mode='rb' closefd=True>
这些只是您通常不必担心的技术细节。每个对象执行一个特定的功能,需要进行更高级I / O争用的人可以混合和匹配这些功能。
答案 1 :(得分:4)
当对象没有自己的__str__
或file
时,它就是对象的文本表示形式。 {{1}}是一个变量,指向在with语句中创建的对象。
答案 2 :(得分:3)
这是open(filename, "a")
上下文管理器调用返回的对象。 _io.TextIOWrapper
是一个file-like object,您可以执行诸如读取,写入,搜索和关闭之类的操作。
执行此操作时:
with thing1 as thing2:
调用方法thing1.__enter__
,并将其返回的内容分配给变量/名称thing2
。
所以是的,在您的示例中file
确实是一个已分配给with
上下文管理器返回的任何对象的变量。在这种情况下,它是_io.TextIOWrapper
对象。这就是你这样做的原因:
print(file)
你得到:
<_io.TextIOWrapper name='Class_A.txt' mode='a' encoding='cp1252'>
...这只是那种对象的字符串表示。
您可以通过这种方式手动获取相同的对象:
file = open(filename, "a").__enter__()
print(file) # same file-like object you were getting before
file.write('a line') # do stuff with it
file.close() # close it
请注意,open(filename, "a").__enter__()
返回的对象与您从open(filename, "a")
获得的对象相同。这是因为__enter__()
对象的_io.TextIOWrapper
方法只返回self
。但是,其他对象并非总是如此。
如果您发现所有这些令人困惑,我建议您阅读更多有关with statement
的信息。