python中read()、readline()、readlnes()区别

原文link: http://www.cnblogs.com/lzhenf/archive/2012/03/06/2382022.html

我们谈到“文本处理”时,我们通常是指处理的内容。Python 将文本文件的内容读入可以操作的字符串变量非常容易。文件对象提供了三个“读”方法: .read()、.readline() 和 .readlines()。每种方法可以接受一个变量以限制每次读取的数据量,但它们通常不使用变量。 .read() 每次读取整个文件,它通常用于将文件内容放到一个字符串变量中。然而 .read() 生成文件内容最直接的字符串表示,但对于连续的面向行的处理,它却是不必要的,并且如果文件大于可用内存,则不可能实现这种处理。

.readline() 和 .readlines() 非常相似。它们都在类似于以下的结构中使用:

 
fh = open('c:\\autoexec.bat')
         for  line in  fh.readlines(): 
         print  line


.readline() 和 .readlines() 之间的差异是后者一次读取整个文件,象 .read() 一样。.readlines() 自动将文件内容分析成一个行的列表,该列表可以由 Python 的 for ... in ... 结构进行处理。另一方面,.readline() 每次只读取一行,通常比 .readlines() 慢得多。仅当没有足够内存可以一次读取整个文件时,才应该使用 .readline()。

文本处理链接:

http://www.ibm.com/developerworks/cn/linux/sdk/python/python-5/index.html

字符串 -- 不可改变的序列

如同大多数高级编程语言一样,变长字符串是 Python 中的基本类型。Python 在“后台”分配内存以保存字符串(或其它值),程序员不必为此操心。Python 还有一些其它高级语言没有的字符串处理功能。

在 Python 中,字符串是“不可改变的序列”。尽管不能“按位置”修改字符串(如字节组),但程序可以引用字符串的元素或子序列,就象使用任何序列一样。Python 使用灵活的“分片”操作来引用子序列,字符片段的格式类似于电子表格中一定范围的行或列。以下交互式会话说明了字符串和字符片段的的用法:


字符串和分片
>>> s = 
        "mary had a little lamb"
>>> s[0] 
        # index is zero-based

        'm'
>>> s[3] = 
        'x' 
        # changing element in-place fails
Traceback (innermost last):
 File 
        "<stdin>", line 1, 
        
          in
         ?
TypeError: object doesn't support item assignment
>>> s[11:18] 
        # 'slice' a subsequence

        'little '
>>> s[:4] 
        # empty slice-begin assumes zero

        'mary'
>>> s[4] 
        # index 4 is not included in slice [:4]

        ' '
>>> s[5:-5] 
        # can use "from end" index with negatives

        'had a little'
>>> s[:5]+s[5:] 
        # slice-begin & slice-end are complimentary

        'mary had a little lamb'
      

另一个功能强大的字符串操作就是简单的 in 关键字。它提供了两个直观有效的构造:


in 关键字
>>> s = 
        "mary had a little lamb"
>>> 
        
          for
         c 
        
          in
         s[11:18]: 
        
          print
         c, 
        # print each char in slice
...
l i t t l e
>>> 
        
          if
         
        'x' 
        
          in
         s: 
        
          print
         
        'got x' 
        # test for char occurrence
...
>>> 
        
          if
         
        'y' 
        
          in
         s: 
        
          print
         
        'got y' 
        # test for char occurrence
...
got y
      

在 Python 中,有几种方法可以构成字符串文字。可以使用单引号或双引号,只要左引号和右引号匹配,常用的还有其它引号的变化形式。如果字符串包含换行符或嵌入引号,三重引号可以很方便地定义这样的字符串,如下例所示:


三重引号的使用
>>> s2 = 
        """Mary had a little lamb
... its fleece was white as snow
... and everywhere that Mary went
... the lamb was sure to go"""
>>> 
        
          print
         s2
Mary had a little lamb
its fleece was white as snow
        
          and
         everywhere that Mary went
the lamb was sure to go
      

使用单引号或三重引号的字符串前面可以加一个字母 "r" 以表示 Python 不应该解释规则表达式特殊字符。例如:


使用 "r-strings"
>>> s3 = 
        "this \n and \n that"
>>> 
        
          print
         s3
this
        
          and

        that
>>> s4 = r
        "this \n and \n that"
>>> 
        
          print
         s4
this \n 
        
          and
         \n that
      

在 "r-strings" 中,可能另外组成换码符的反斜杠被当作是常规反斜杠。在以后的规则表达式讨论中会进一步说明这个话题。


文件和字符串变量

我们谈到“文本处理”时,我们通常是指处理的内容。Python 将文本文件的内容读入可以操作的字符串变量非常容易。文件对象提供了三个“读”方法: .read()、.readline() 和 .readlines()。每种方法可以接受一个变量以限制每次读取的数据量,但它们通常不使用变量。 .read() 每次读取整个文件,它通常用于将文件内容放到一个字符串变量中。然而 .read() 生成文件内容最直接的字符串表示,但对于连续的面向行的处理,它却是不必要的,并且如果文件大于可用内存,则不可能实现这种处理。

.readline() 和 .readlines() 非常相似。它们都在类似于以下的结构中使用:


Python .readlines() 示例
        fh = open(
        'c:\\autoexec.bat')
        
          for
         line 
        
          in
         fh.readlines():
 
        
          print
         line
 
      

.readline() 和 .readlines() 之间的差异是后者一次读取整个文件,象 .read() 一样。.readlines() 自动将文件内容分析成一个行的列表,该列表可以由 Python 的 for ... in ... 结构进行处理。另一方面,.readline() 每次只读取一行,通常比 .readlines() 慢得多。仅当没有足够内存可以一次读取整个文件时,才应该使用 .readline()。

如果正在使用处理文件的标准模块,可以使用 cStringIO 模块将字符串转换成“虚拟文件”(如果需要生成模块的子类,可以使用 StringIO 模块,初学者未必要这样做)。例如:


cStringIO 模块
>>> 
        
          import
         cStringIO
>>> fh = cStringIO.StringIO()
>>> fh.write(
        "mary had a little lamb")
>>> fh.getvalue()
        'mary had a little lamb'
>>> fh.seek(5)
>>> fh.write(
        'ATE')
>>> fh.getvalue()
        'mary ATE a little lamb'
      

但是,请记住,cStringIO“虚拟文件”不是永久的,这一点与真正的文件不同。如果不保存它(如将它写入一个真正的文件,或者使用 shelve 模块或数据库),则程序结束时,它将消失。


标准模块:string

string 模块也许是 Python 1.5.* 标准发行版中最常用的模块。实际上,在 Python 1.6 或更高版本中,string 模块中的功能将作为内置字符串方法(在撰写本文时,详细信息尚未发布)。当然,任何执行文本处理任务的程序也许应该用以下这行开头:


开始使用 string 的方法
      import string

一般经验法则告诉我们,如果 可以 使用 string 模块完成任务,那么那就是 正确 的方法。与 re(规则表达式)相比,string 函数通常更快速,大多数情况下他们更易于理解和维护。第三方 Python 模块,包括某些用 C 编写的快速模块,适用于专门的任务,但可移植性和熟悉性都建议只要可能就使用 string。如果您习惯于使用其它语言,也会有例外,但不如您想像的那样多。

string 模块包含了几种类型的事物,如函数、方法和类;它还包含了公共常量的字符串。例如:


string 用法例 1
>>> 
        
          import
         string
>>> string.whitespace
        '\011\012\013\014\015 '
>>> string.uppercase
        'ABCDEFGHIJKLMNOPQRSTUVWXYZ'
      

虽然可以用手写出这些常量,string 版本或多或少确保了常量对于运行 Python 脚本的国家语言和平台将是正确的。

string 还包括了以常见方式(可以结合这些方式来构成几种罕见的转换)转换字符串的函数。例如:


string 用法例 2
>>> 
        
          import
         string
>>> s = 
        "mary had a little lamb"
>>> string.capwords(s)
        'Mary Had A Little Lamb'
>>> string.replace(s, 
        'little', 
        'ferocious')
        'mary had a ferocious lamb'
      

还有许多没有在这里具体说明的其它转换;可以在 Python 手册中查找详细信息。

还可以使用 string 函数来报告字符串属性,如子串的长度或位置,例如:


string 用法例 3
>>> 
        
          import
         string
>>> s = 
        "mary had a little lamb"
>>> string.find(s, 
        'had')5>>> string.count(s, 
        'a')4
      

最后,string 提供了非常 Python 化的奇特事物。.split() 和 .join() 对提供了在字符串和字节组之间转换的迅捷方法,您会发现它们非常有用。用法很简单:


string 用法例 4
>>> 
        
          import
         string>>> s = 
        "mary had a little lamb"
>>> L = string.split(s)
>>> L
[
        'mary', 
        'had', 
        'a', 
        'little', 
        'lamb']
>>> string.join(L, 
        "-")
        'mary-had-a-little-lamb'
      

当然,除了 .join() 之外,也许会利用列表来做其它事(如某些涉及我们熟悉的 for ... in ... 结构的事情)。


标准模块:re

re 模块废弃了在老的 Python 代码中使用的 regex 和 regsub 模块。虽然相对于 regex 仍然有几个有限的优点,不过这些优点微不足道,不值得在新代码中使用。过时的模块可能会从未来的 Python 发行版中删除,并且 1.6 版可能有一个改进的接口兼容的 re 模块。所以,规则表达式仍将使用 re 模块。

规则表达式很复杂。也许有人会撰写关于这个主题的书,但实际上,已经有许多人这样做了!本文尝试捕捉规则表达式的“完全形态”,让读者可以掌握它。

规则表达式是一种很简练方法,用于描述可能在文本中出现的模式。是否会出现某些字符?是否按特定顺序出现?子模式是否会重复一定次数?其它子模式是否会排除在匹配之外?从概念上说,似乎不能用自然语言了直观地描述模式。诀窍是使用规则表达式的简洁语法来编码这种描述。

当处理规则表达式时,将它作为它自己的编程问题来处理,即使只涉及一或两行代码;这些行有效地构成了一个小程序。

从最小处着手。从最基本上看,任何规则表达式都涉及匹配特定的“字符类”。最简单的字符类就是单个字符,它在模式中只是一个字。通常,您希望匹配一类字符。可以通过将类括在方括号内来表明这是一个类;在括号中,可以有一组字符或者用破折号指定的字符范围。还可以使用许多命名字符类来确定您的平台和国家语言。以下是一些示例:


字符类
>>> 
        
          import
         re
>>> s = 
        "mary had a little lamb"
>>> 
        
          if
         re.search(
        "m", s): 
        
          print
         
        "Match!" 
        # char literal
Match!
>>> 
        
          if
         re.search(
        "[@A-Z]", s): 
        
          print
         
        "Match!" 
        # char class
... 
        # match either at-sign or capital letter
...
>>> 
        
          if
         re.search(
        "\d", s): 
        
          print
         
        "Match!" 
        # digits class
...
      

可以将字符类看作是规则表达式的“原子”,通常会将那些原子组合成“分子”。可以结合使用 分组循环 来完成此操作。由括号表示分组:括号中包含的任何子表达式都被看作是用于以后分组或循环的原子。循环则由以下几个运算符中的某一个来表示:"*" 表示“零或多”;"+" 表示“一或多”;"?" 表示“零或一”。例如,请看以下示例:


样本规则表达式
ABC([d-w]*\d\d?)+XYZ

对于要匹配这个表达式的字符串,它必须以 "ABC" 开头、以 "XYZ" 结尾 -- 但它的中间必须要有什么呢?中间子表达式是 ([d-w]*\d\d?),而且后面跟了“一或多”运算符。所以,字符串的中间必须包括一个(或者两个,或者一千个)与括号中的子表达式匹配的字符或字符串。字符串 "ABCXYZ" 不匹配,因为它的中间没有必要的字符。

不过这个内部子表达式是什么呢?它以 d-w 范围内的 零或多个 字母开头。一定要注意:零字母是有效匹配,虽然使用英语单词 "some"(一些)来描述它,可能会感到很别扭。接着,字符串必须 恰好有一个数字;然后有 零或一个 附加数字。(第一个数字字符类没有循环运算符,所以它只出现一次。第二个数字字符类有 "?" 运算符。)总而言之,这将翻译成“一个或两个数字”。以下是一些与规则表达式匹配的字符串:


匹配样本表达式的字符串
ABC1234567890XYZ
ABCd12e1f37g3XYZ
ABC1XYZ

还有一些表达式与规则表达式 匹配(想一想,它们为什么不匹配):


不匹配样本表达式的字符串
ABC123456789dXYZ
ABCdefghijklmnopqrstuvwXYZ
ABcd12e1f37g3XYZ
ABC12345%67890XYZ
ABCD12E1F37G3XYZ

需要一些练习才能习惯创建和理解规则表达式。但是,一旦掌握了规则表达式,您就具有了强大的表达能力。也就是说,转而使用规则表达式解决问题通常会很容易,而这类问题实际上可以使用更简单(而且更快速)的工具,如 string,来解决。


参考资料


<think>嗯,用户问的是Pythonreadreadlinereadlines的区别。首先,我需要回忆这三个方法的具体用法区别。记得它们都是用来读取文件内容的,但具体行为不同。 首先,read()方法应该是读取整个文件内容,返回一个字符串。如果指定了size参数,就读取指定大小的数据。对吧?比如f.read(10)会读10个字节。 然后是readline(),这个应该是每次读取一行,保留行尾的换行符。如果文件很大,逐行读取可以节省内存。不过如果反复调用的话,会不会自动移动到下一行?是的,因为文件对象会记录当前位置。 接下来是readlines(),它会把所有行读到一个列表里,每个元素是一行内容,包括换行符。可能需要注意内存问题,因为大文件的话列表会很大。不过现在用户可能更关心基本区别。 用户可能需要实际例子来理解它们的区别。比如用同一个文件分别展示三个方法的输出结果。还要提醒他们文件指针的位置变化,比如调用read()后,再调用readline()会不会返回空,因为已经读到文件末尾了。 可能用户在处理日志文件、配置文件时,需要逐行处理,这时候用readline或者循环文件对象更高效。而readlines适合需要所有行的情况,比如处理每一行后存储起来。 还要注意,在Python中,通常推荐直接用for循环迭代文件对象,这样更高效,因为不会一次性加载所有内容到内存。这点可能也值得提到,作为最佳实践。 有没有特殊情况需要注意?比如文件没有换行符时,readline的行为?或者不同操作系统下的换行符处理?不过用户的问题可能更基础,暂时不需要深入这些细节。 总结的话,应该分点说明每个方法的功能、返回值类型、适用场景,以及注意事项。结构要清晰,让用户容易理解。</think>在Python中,`read`、`readline``readlines`是文件读取的三种常用方法,它们的核心区别在于**读取方式****返回值类型**。以下是逐步说明: --- ### 1. **`read([size])`** - **功能** 一次性读取文件的**全部内容**(或指定字节数),返回**字符串类型**。 - **参数** `size`(可选):指定读取的字节数。若省略或为负数,则读取整个文件。 - **示例** ```python with open("test.txt", "r") as f: content = f.read() # 读取整个文件 partial = f.read(10) # 读取前10个字符(若未到文件末尾) ``` - **适用场景** 适合小文件或需要一次性处理全部内容的场景。 - **注意事项** 大文件可能占用过高内存。 --- ### 2. **`readline([size])`** - **功能** 逐行读取文件内容,返回**字符串类型**(包含换行符`\n`)。 - **参数** `size`(可选):限制单行读取的字节数。若省略,则读取整行。 - **示例** ```python with open("test.txt", "r") as f: line1 = f.readline() # 读取第一行(包含换行符) line2 = f.readline() # 读取第二行 ``` - **适用场景** 逐行处理大文件(如日志分析),节省内存。 - **注意事项** 需手动循环读取所有行,或结合`while`使用。 --- ### 3. **`readlines([hint])`** - **功能** 读取文件的**所有行**,返回**列表类型**,每行内容为列表元素(含换行符)。 - **参数** `hint`(可选):限制读取的总字节数。若省略,读取全部。 - **示例** ```python with open("test.txt", "r") as f: lines = f.readlines() # 返回列表,如["line1\n", "line2\n"] ``` - **适用场景** 需要按行操作且文件不大的情况。 - **注意事项** 大文件可能导致内存溢出。 --- ### 对比总结 | 方法 | 返回值类型 | 内存占用 | 适用场景 | |-------------|------------|----------|------------------| | `read()` | 字符串 | 高 | 小文件整体读取 | | `readline()`| 字符串 | 低 | 逐行处理大文件 | | `readlines()`| 列表 | 高 | 需要按行操作小文件 | --- ### 扩展建议 - **更高效的逐行读取方式** 直接遍历文件对象(无需`readlines`): ```python with open("test.txt", "r") as f: for line in f: # 逐行迭代,内存友好 print(line.strip()) ``` - **文件指针位置** 每次调用这些方法后,文件指针会移动到已读取内容的末尾,影响后续操作。可通过`f.seek(0)`重置指针位置。 希望这个对比能帮助您合理选择文件读取方法!
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值