我刚开始使用Python,因为我的背景是更低级的语言(java,C ++),所以我真的无法得到一些东西。
因此,在python中,例如,可以通过打开文本文件来创建文件变量,然后像这样遍历其行:
f = open(sys.argv[1])
for line in f:
#do something
但是,如果我尝试f[0]
,则解释器会出错。那么f
对象具有什么结构?如果我可以将for ... in ... :
循环应用于对象,我通常如何知道?
答案 0 :(得分:7)
f
是file object。文档列出了它的结构,所以我只解释索引/迭代行为。
对象只有在实现__getitem__
时才可索引,您可以通过调用hasattr(f, '__getitem__')
或只调用f[0]
并查看是否抛出错误来检查对象。事实上,这正是您的错误消息告诉您的:
TypeError: 'file' object has no attribute '__getitem__'
文件对象不可索引。您可以调用f.readlines()
并返回行列表,这些行本身是可索引的。
实现__iter__
的对象可以使用for ... in ...
语法进行迭代。现在实际上有两种类型的可迭代对象:容器对象和迭代器对象。 Iterator对象实现两种方法:__iter__
和__next__
。容器对象只实现__iter__
并返回一个迭代器对象,这实际上就是你要迭代的东西。文件对象是它们自己的迭代器,因为它们实现了两种方法。
如果要获取iterable中的下一个项目,可以使用next()
函数:
first_line = next(f)
second_line = next(f)
next_line_that_starts_with_0 = next(line for line in f if line.startswith('0'))
需要注意的一点是:迭代通常不是“可重绕的”,所以一旦你完成了迭代,你就无法真正回归。要“回放”文件对象,可以使用f.seek(0)
,这会将当前位置设置回文件的开头。
答案 1 :(得分:4)
1)f不是列表。是否有任何书籍,教程或网站告诉你f是一个列表?如果没有,为什么你认为你可以把f作为一个列表?您当然不能将C ++或Java中的文件视为数组吗?为什么不呢?
2)在python中,for循环执行以下操作:
a) The for loop calls __iter__() on the object to the right of 'in',
e.g. f.__iter__().
b) The for loop repeatedly calls next() (or __next__() in python 3) on whatever
f.__iter__() returns.
因此,f.__iter__()
可以返回一个对象,以便在调用next()时执行任何操作。只是碰巧Guido决定f.__iter__()
返回的对象应该在调用next()方法时提供文件中的行。
我怎么知道一般情况下,如果我可以申请......在...:循环到一个 对象
如果对象具有__iter__()
方法,并且__iter__()
方法返回带有next()方法的对象,则可以对其应用for-in循环。或者换句话说,您可以从经验中了解哪些对象实现了迭代器协议。
答案 2 :(得分:2)
这证明了支持索引,切片和有限迭代的sequence type与不支持索引或切片的iterator type之间的差异,但是更高级的迭代,维持内部状态这样做。
文件对象是后者的一个例子。您可以将内容提取为行,并通过readlines
方法将其存储在序列类型(特别是列表)中,正如其他人所指出的那样。
答案 3 :(得分:2)
在Python中,每个数据项都是一个Python对象。所以open()
返回给你的是一个对象;具体来说,它是一个file
对象,表示文件句柄。
您已经知道如何执行此操作:
handle = open("some_file.txt, "r")
从概念上讲,这与C中的等价物非常相似:
FILE *handle;
handle = fopen("some_file.txt", "r");
在C中,您可以对handle
变量执行的唯一有用的操作是将其传递给fread()
之类的调用。在Python中,该对象具有与之关联的方法功能。所以,这里是C从文件中读取100个字节然后关闭它:
FILE *handle;
handle = fopen("some_file.txt", "r");
result = fread(buffer, 1, 100 handle); // read 100 bytes into buffer
fclose(handle);
这是等效的Python:
handle = open("some_file.txt", "r");
handle.read(100)
handle.close()
了解Python函数和对象的更多信息的好方法是使用Python提示符中的内置help()
命令。尝试help(open)
它并没有告诉你太多,但确实告诉你它返回一个文件对象。然后尝试help(file)
,现在您可以获得大量信息。您可以阅读.close()
方法,.read()
以及.readlines()
等其他方法。
但是让你感到困惑的是迭代句柄对象。由于一个非常常见的情况是从文件中读取行,因此Python使文件句柄作为迭代器工作,当您迭代时,您从文件中一次获得一行。
Python中的列表对象都是可索引的和可迭代的,因此如果您有一个名为a
的列表,则可以a[i]
或{ {1}}。按位置for x in a:
查找项目正在编制索引。文件句柄对象不支持索引,但支持迭代。
在这里的几个答案中,您将看到a[i]
语句。这是Python中的最佳实践。 with
语句仅适用于Python中的某些对象;对象必须支持几个特殊的方法函数。您现在真正需要知道的关于with
的所有内容是,当您可以使用它时,可以为您完成一些初始化和完成工作。在打开文件的情况下,with
语句将为您关闭文件。最重要的是with
语句保证即使代码引发异常也会完成最终化。
这是上面例子的惯用Python:
with
答案 4 :(得分:1)
您要找的是readlines
http://docs.python.org/2/library/stdtypes.html#file.readlines
file_lines = f.readlines()
for line in file_lines:
print line
print file_lines[0] # You can access an element by index
答案 5 :(得分:1)
您能够这样做是因为file object
是可迭代的。
答案 6 :(得分:0)
文件变量类似于C中的文件处理程序。您打开它,对其进行操作(读取,写入)并最终关闭。
handler.read() # read all file content at once
handler.write(blob) # write there something
handler.readlines() # read list with lines
for line in handler:
print line # iterate lines nicely
最后一个示例优于for line in handler.readlines()
,因为第一个示例在您需要时读取行,第二个示例一次消耗所有行(可能是大文件的麻烦)
答案 7 :(得分:0)
创建f后,它就是一个文件对象。 readlines是文件对象的方法之一。
for line in f.readlines():
启动一个循环,允许您编写的其他代码一次处理文件的line
。你可以使用for循环,因为readlines()返回的对象是可迭代的。
答案 8 :(得分:0)
您始终可以使用dir(f)查看f的结构,f是文件对象
['__class__', '__delattr__', '__doc__', '__enter__', '__exit__', '__format__', '__getattribute__', '__hash__', '__init__', '__iter__', '__new__', '__reduce__', '__reduce_ex__', '__repr__', '__setattr__', '__sizeof__', '__str__', '__subclasshook__', 'close', 'closed', 'encoding', 'errors', 'fileno', 'flush', 'isatty', 'mode', 'name', 'newlines', 'next', 'read', 'readinto', 'readline', 'readlines', 'seek', 'softspace', 'tell', 'truncate', 'write', 'writelines', 'xreadlines']
答案 9 :(得分:0)
解释器出错
TypeError: 'file' object has no attribute '__getitem__'
告诉您类型file
不允许像f[0]
那样编制索引,依此类推。如果类型具有属性__getitem__
,则它允许索引,否则不允许。对于文件,它是后者。
您可以通过此操作了解有关文件的更多信息。
>>> fileTest = open('fileName')
>>> type(fileTest)
<type 'file'>
>>> dir(fileTest)
['__class__', '__delattr__', '__doc__', '__enter__', '__exit__', '__format__', '__getattribute__', '__hash__', '__init__', '__iter__', '__new__', '__reduce__', '__reduce_ex__', '__repr__', '__setattr__', '__sizeof__', '__str__', '__subclasshook__', 'close', 'closed', 'encoding', 'errors', 'fileno', 'flush', 'isatty', 'mode', 'name', 'newlines', 'next', 'read', 'readinto', 'readline', 'readlines', 'seek', 'softspace', 'tell', 'truncate', 'write', 'writelines', 'xreadlines']
for
循环通常可以应用于任何可迭代的结构。
如果你想要一个行列表,那么你可以这样做。
>>> with open('fileName') as f:
lines = f.readlines()
或者通过做,
>>> with open('fileName') as f:
lines = [line for line in f]