文本处理基础

PythonPythonBeginner
立即练习

This tutorial is from open-source community. Access the source code

💡 本教程由 AI 辅助翻译自英文原版。如需查看原文,您可以 切换至英文原版

简介

本节介绍处理文本的方法。

表示字面文本

字符串字面量在程序中用引号括起来书写。

## 单引号
a = 'Yeah but no but yeah but...'

## 双引号
b = "computer says no"

## 三引号
c = '''
Look into my eyes, look into my eyes, the eyes, the eyes, the eyes,
not around the eyes,
don't look around the eyes,
look into my eyes, you're under.
'''

通常情况下,字符串只能跨一行。三引号会捕获跨多行包含的所有文本,包括所有格式。

使用单引号(')和双引号(")没有区别。但是,用于开始字符串的引号类型必须用于结束它

字符串转义码

转义码用于表示控制字符以及那些无法直接在键盘上轻松键入的字符。以下是一些常见的转义码:

'\n'      换行符
'\r'      回车符
'\t'      制表符
'\''      字面单引号
'\"'      字面双引号
'\\'      字面反斜杠

字符串表示形式

字符串中的每个字符在内部都作为一个所谓的 Unicode“码点”存储,它是一个整数。你可以使用以下转义序列指定确切的码点值:

a = '\xf1'          ## a = 'ñ'
b = '\u2200'        ## b = '∀'
c = '\U0001D122'    ## c = '𝄢'
d = '\N{FOR ALL}'   ## d = '∀'

Unicode 字符数据库 是所有可用字符代码的参考。

字符串索引

字符串在访问单个字符时的工作方式类似于数组。你使用从 0 开始的整数索引。负索引指定相对于字符串末尾的位置。

a = 'Hello world'
b = a[0]          ## 'H'
c = a[4]          ## 'o'
d = a[-1]         ## 'd' (字符串末尾)

你还可以使用 : 指定索引范围来切片或选择子字符串。

d = a[:5]     ## 'Hello'
e = a[6:]     ## 'world'
f = a[3:8]    ## 'lo wo'
g = a[-5:]    ## 'world'

结束索引处的字符不包括在内。缺失的索引假定为字符串的开头或结尾。

字符串操作

拼接、长度、成员关系和复制。

## 拼接 (+)
a = 'Hello' + 'World'   ## 'HelloWorld'
b = 'Say'+ a          ## 'Say HelloWorld'

## 长度 (len)
s = 'Hello'
len(s)                  ## 5

## 成员测试 (`in`, `not in`)
t = 'e' in s            ## True
f = 'x' in s            ## False
g = 'hi' not in s       ## True

## 复制 (s * n)
rep = s * 5             ## 'HelloHelloHelloHelloHello'

字符串方法

字符串有一些方法可对字符串数据执行各种操作。

示例:去除任何前导/尾随空白字符。

s =' Hello '
t = s.strip()     ## 'Hello'

示例:大小写转换。

s = 'Hello'
l = s.lower()     ## 'hello'
u = s.upper()     ## 'HELLO'

示例:替换文本。

s = 'Hello world'
t = s.replace('Hello ', 'Hallo')   ## 'Hallo world'

更多字符串方法

字符串还有许多其他用于测试和操作文本数据的方法。以下是一小部分方法:

s.endswith(suffix)     ## 检查字符串是否以 suffix 结尾
s.find(t)              ## 在 s 中首次出现 t 的位置
s.index(t)             ## 在 s 中首次出现 t 的位置
s.isalpha()            ## 检查字符是否为字母
s.isdigit()            ## 检查字符是否为数字
s.islower()            ## 检查字符是否为小写
s.isupper()            ## 检查字符是否为大写
s.join(slist)          ## 使用 s 作为分隔符连接字符串列表
s.lower()              ## 转换为小写
s.replace(old,new)     ## 替换文本
s.rfind(t)             ## 从字符串末尾开始搜索 t
s.rindex(t)            ## 从字符串末尾开始搜索 t
s.split([delim])       ## 将字符串拆分为子字符串列表
s.startswith(prefix)   ## 检查字符串是否以 prefix 开头
s.strip()              ## 去除前导/尾随空格
s.upper()              ## 转换为大写

字符串的不可变性

字符串是“不可变的”,即只读的。一旦创建,其值就不能被更改。

>>> s = 'Hello World'
>>> s[1] = 'a'
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
TypeError:'str' object does not support item assignment
>>>

所有操作和处理字符串数据的方法,总是会创建新的字符串。

字符串转换

使用 str() 将任何值转换为字符串。结果是一个字符串,其包含的文本与 print() 语句生成的文本相同。

>>> x = 42
>>> str(x)
'42'
>>>

字节串

一串 8 位字节,通常在底层 I/O 中遇到,写法如下:

data = b'Hello World\r\n'

通过在第一个引号前加一个小写的 b,你指定这是一个字节串,而不是文本串。

大多数常见的字符串操作都适用。

len(data)                         ## 13
data[0:5]                         ## b'Hello'
data.replace(b'Hello', b'Cruel')  ## b'Cruel World\r\n'

索引有点不同,因为它返回的字节值是整数。

data[0]   ## 72 ('H'的 ASCII 码)

与文本串之间的转换。

text = data.decode('utf-8') ## 字节 -> 文本
data = text.encode('utf-8') ## 文本 -> 字节

'utf-8' 参数指定了一种字符编码。其他常见的值包括 'ascii''latin1'

原始字符串

原始字符串是带有未解释反斜杠的字符串字面量。它们通过在初始引号前加上小写的“r”来指定。

>>> rs = r'c:\newdata\test' ## 原始(未解释的反斜杠)
>>> rs
'c:\\newdata\\test'

字符串就是包含在其中的字面文本,完全按照输入的原样。这在反斜杠具有特殊意义的情况下很有用。例如:文件名、正则表达式等。

f 字符串

一种带有格式化表达式替换的字符串。

>>> name = 'IBM'
>>> shares = 100
>>> price = 91.1
>>> a = f'{name:>10s} {shares:10d} {price:10.2f}'
>>> a
'       IBM        100      91.10'
>>> b = f'Cost = ${shares*price:0.2f}'
>>> b
'Cost = $9110.00'
>>>

注意:这需要 Python 3.6 或更高版本。 格式代码的含义将在后面介绍。

在这些练习中,你将对 Python 字符串类型进行操作实验。你应该在 Python 交互式提示符下进行,这样可以轻松看到结果。重要提示:

在需要与解释器交互的练习中,>>> 是当 Python 希望你输入新语句时出现的解释器提示符。练习中的一些语句跨越多行 —— 要运行这些语句,你可能需要按几次“回车”。提醒一下,在处理这些示例时你 不要 输入 >>>

首先定义一个包含一系列股票代码的字符串,如下所示:

>>> symbols = 'AAPL,IBM,MSFT,YHOO,SCO'
>>>

练习 1.13:提取单个字符和子字符串

字符串是字符数组。尝试提取几个字符:

>>> symbols[0]
?
>>> symbols[1]
?
>>> symbols[2]
?
>>> symbols[-1]        ## 最后一个字符
?
>>> symbols[-2]        ## 负索引从字符串末尾开始
?
>>>

在 Python 中,字符串是只读的。

通过尝试将 symbols 的第一个字符改为小写的 'a' 来验证这一点。

>>> symbols[0] = 'a'
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
TypeError:'str' 对象不支持项赋值
>>>

练习 1.14:字符串拼接

虽然字符串数据是只读的,但你总是可以将变量重新赋值为新创建的字符串。

尝试以下语句,将新符号“GOOG”拼接到 symbols 的末尾:

>>> symbols = symbols + 'GOOG'
>>> symbols
'AAPL,IBM,MSFT,YHOO,SCOGOOG'
>>>

哎呀!这不是你想要的。修正它,使 symbols 变量的值为 'AAPL,IBM,MSFT,YHOO,SCO,GOOG'

>>> symbols =?
>>> symbols
'AAPL,IBM,MSFT,YHOO,SCO,GOOG'
>>>

在字符串开头添加 'HPQ'

>>> symbols =?
>>> symbols
'HPQ,AAPL,IBM,MSFT,YHOO,SCO,GOOG'
>>>

在这些示例中,看起来原始字符串好像被修改了,这显然违反了字符串只读的特性。其实并非如此。每次对字符串进行操作都会创建一个全新的字符串。当变量名 symbols 被重新赋值时,它指向新创建的字符串。之后,旧字符串会因为不再被使用而被销毁。

练习 1.15:成员测试(子字符串测试)

使用 in 运算符来检查子字符串。在交互式提示符下,尝试以下操作:

>>> 'IBM' in symbols
?
>>> 'AA' in symbols
True
>>> 'CAT' in symbols
?
>>>

为什么对 'AA' 的检查返回 True

练习 1.16:字符串方法

在 Python 交互式提示符下,尝试使用一些字符串方法。

>>> symbols.lower()
?
>>> symbols
?
>>>

记住,字符串始终是只读的。如果你想保存操作结果,需要将其存储在变量中:

>>> lowersyms = symbols.lower()
>>>

再尝试一些其他操作:

>>> symbols.find('MSFT')
?
>>> symbols[13:17]
?
>>> symbols = symbols.replace('SCO','DOA')
>>> symbols
?
>>> name ='  IBM   \n'
>>> name = name.strip()    ## 移除周围的空白字符
>>> name
?
>>>

练习 1.17:f 字符串

有时你想创建一个字符串,并将变量的值嵌入其中。

要做到这一点,请使用 f 字符串。例如:

>>> name = 'IBM'
>>> shares = 100
>>> price = 91.1
>>> f'{shares} shares of {name} at ${price:0.2f}'
'100 shares of IBM at $91.10'
>>>

修改练习 1.10 中的 mortgage.py 程序,使用 f 字符串来生成其输出。尽量使输出格式整齐。

✨ 查看解决方案并练习

练习 1.18:正则表达式

基本字符串操作的一个局限性在于它们不支持任何高级模式匹配。为此,你需要使用 Python 的 re 模块和正则表达式。正则表达式处理是一个很大的主题,但这里有一个简短的示例:

>>> text = 'Today is 3/27/2018. Tomorrow is 3/28/2018.'
>>> ## 查找所有日期出现的位置
>>> import re
>>> re.findall(r'\d+/\d+/\d+', text)
['3/27/2018', '3/28/2018']
>>> ## 用替换文本替换所有日期出现的位置
>>> re.sub(r'(\d+)/(\d+)/(\d+)', r'\3-\1-\2', text)
'Today is 2018-3-27. Tomorrow is 2018-3-28.'
>>>

有关 re 模块的更多信息,请参阅官方文档 https://docs.python.org/library/re.html

注释

当你开始使用解释器进行实验时,你通常想了解更多关于不同对象支持的操作。例如,你如何找出字符串上可用的操作?

根据你的 Python 环境,你可能可以通过按 Tab 键补全来查看可用方法的列表。例如,尝试输入以下内容:

>>> s = 'hello world'
>>> s.<tab键>
>>>

如果按 Tab 键没有任何反应,你可以使用内置的 dir() 函数。例如:

>>> s = 'hello'
>>> dir(s)
['__add__', '__class__', '__contains__',..., 'find', 'format',
'index', 'isalnum', 'isalpha', 'isdigit', 'islower', 'isspace',
'istitle', 'isupper', 'join', 'ljust', 'lower', 'lstrip', 'partition',
'replace', 'rfind', 'rindex', 'rjust', 'rpartition', 'rsplit',
'rstrip','split','splitlines','startswith','strip','swapcase',
'title', 'translate', 'upper', 'zfill']
>>>

dir() 会生成一个可以出现在 (.) 之后的所有操作的列表。使用 help() 命令获取有关特定操作的更多信息:

>>> help(s.upper)
关于内置函数upper的帮助文档:

upper(...)
    S.upper() -> string

    返回字符串S转换为大写后的副本。
>>>

总结

恭喜你!你已经完成了字符串实验。你可以在 LabEx 中练习更多实验来提升你的技能。