《Python自然语言处理》——1.2 近观Python:将文本当做词链表

简介:

本节书摘来异步社区《Python自然语言处理》一书中的第1章,第1.2节,作者:【美】Steven Bird , Ewan Klein , Edward Loper,更多章节内容可以访问云栖社区“异步社区”公众号查看

1.2 近观Python:将文本当做词链表

大家已经学习过Python编程语言的一些重要元素。下面进行简单的系统复习。

链表
文本是什么?一方面,它是一页纸上的符号序列,就像这页纸一样。另一方面,它是章节的序列,每一章由小节序列组成,这些小节由段落序列组成,以此类推。然而,对于我们而言,认为文本不外乎是单词和标点符号的序列。下面是如何展示Python中《白鲸记》的开篇句。

>>> sent1 = ['Call', 'me', 'Ishmael', '.']
>>>```
在提示符后面,输入自己命名的sent1,后跟一个等号,然后是一些引用的词汇,中间以逗号分割并用括号包围。方括号里的内容在Python中叫做链表,是存储文本的方式。可以通过输入名字①来查阅文本。同样可以查询文本的长度②,甚至可以在自己的函数lexical_diversity()中使用③。

sent1①
['Call', 'me', 'Ishmael', '.']
len(sent1) ②

4

lexical_diversity(sent1) ③

1.0

定义一些链表,将每个文本开始的句子定义为sent2…sent9。下面只检查其中的两个。你可以在Python解释器中查看其余的(如果得到的是一个错误表达:sent2没有定义,你需要先输入from nltk.book import *)。

>>> sent2
['The', 'family', 'of', 'Dashwood', 'had', 'long',
'been', 'settled', 'in', 'Sussex', '.']
>>> sent3
['In', 'the', 'beginning', 'God', 'created', 'the',
'heaven', 'and', 'the', 'earth', '.']
>>>```
提示 轮到你来:

通过输入名字、等号和词链表, 组建一些你自己想要的句子,如ex1 = ['Monty', 'Python', 'and', 'the', 'Holy', 'Grail']。重复使用一些1.1节中的其他Python操作,如:sorted(ex1),len(set(ex1)),ex1.count('the')。
令人惊喜的是,可以对链表使用Python加法运算。两个链表相加①能够创造出一个新的链表,包括第一个链表的全部,并附着第二个链表的全部。

['Monty', 'Python'] + ['and', 'the', 'Holy', 'Grail'] ①

['Monty', 'Python', 'and', 'the', 'Holy', 'Grail']`
提示

这种加法操作的特殊用途叫做连接;它将多个链表组合为一个链表。可以通过把句子连接起来组成一个文本。
不必逐字地输入链表,可以使用简短的名字来引用预先定义好的链表。

>> sent4 + sent1
['Fellow', '-', 'Citizens', 'of', 'the', 'Senate', 'and', 'of', 'the',
'House', 'of', 'Representatives', ':', 'Call', 'me', 'Ishmael', '.']
>>>```
如果想要在链表中增加一个单独的元素该如何做?这种操作叫做追加。当对一个链表使用append()时,链表自身会随着操作而更新。

sent1.append("Some")
sent1

['Call', 'me', 'Ishmael', '.', 'Some']

索引列表
正如已经看到的,Python中的文本是一个词汇的链表,用括号和引号来表示。就像处理一页普通的文本,我们可以使用len(text1)来计算text1的全部词数,使用text1.count('heaven')来计算一个文本中特定词出现的次数,如heaven。

稍微耐心些,我们可以挑选出一篇文本中的第1个、第173个甚至第14278个词。类似的,也可以通过在链表中出现的次序找出Python链表的元素。表示这个位置的数字叫做这个元素的索引。在文本名称后面的方括号里写下索引,Python就会显示出文本中这个索引处——例如文本中第173个词。

>>> text4[173]
'awaken'
>>>```
也可以反过来做;找出一个词第一次出现时的索引。

text4.index('awaken')

173

索引是一种常见的用来获取文本中词汇的方式,或者,更通俗地讲,任何列表中的元素。通过Python也可以获取子链表,从大文本中任意抽取语言片段,术语叫做切片。

>>> text5[16715:16735]
['U86', 'thats', 'why', 'something', 'like', 'gamefly', 'is', 'so', 'good',
'because', 'you', 'can', 'actually', 'play', 'a', 'full', 'game', 'without',
'buying', 'it']
>>> text6[1600:1625]
['We', "'", 're', 'an', 'anarcho', '-', 'syndicalist', 'commune', '.', 'We',
'take', 'it', 'in', 'turns', 'to', 'act', 'as', 'a', 'sort', 'of', 'executive',
'officer', 'for', 'the', 'week']
>>>```
索引还有一些微妙之处,我们将在下面的句子中体会这些。

sent = ['word1', 'word2', 'word3', 'word4', 'word5',

...     'word6', 'word7', 'word8', 'word9', 'word10']

sent[0]

'word1'

sent[9]

'word10'

需要注意的是,索引从零开始:第0个元素写作sent[0],其实是第1个词“word1”;而句子的第9个元素是“word10”。原因很简单:Python从计算机内存中的链表获取内容的时候,需要告诉它向前多少个元素。因此,向前0个元素使它留在第一个元素上。

提示

这种从零算起的做法刚开始接触会有些混乱,但这是现代编程语言普遍使用的。19XY是20世纪中的一年,如果你已经掌握了这样的计数世纪的系统,或者如果你生活在一个建筑物楼层编号从1开始的国家,你很快就会掌握它的窍门,步行n-1级楼梯能够到达第n层。
现在,如果我们不小心使用的索引量过大就会产生错误。

>>> sent[10] 
Traceback (most recent call last):
 File "<stdin>", line 1, in ?
IndexError: list index out of range
>>>```
这不是语法错误,因为程序片段在语法上是正确的。相反,它是一个运行时错误,它会产生一个回溯消息显示错误的上下文,并标注错误的名称:IndexError,以及简要的解释说明。

再次使用构造的句子仔细看看切片,这里我们发现切片5:8包含索引5、6和7的句子元素。

sent[5:8]

['word6', 'word7', 'word8']

sent[5]

'word6'

sent[6]

'word7'

sent[7]

'word8'

按照惯例,m:n表示元素m…n-1。正如下一个例子所示,如果切片从链表第一个元素开始,可以省略第一个数字①;如果切片到链表最后一个元素处结尾,则可以省略第二个数字②:

>>> sent[:3] ①
['word1', 'word2', 'word3']
>>> text2[141525:] ②
['among', 'the', 'merits', 'and', 'the', 'happiness', 'of', 'Elinor', 'and', 'Marianne',
',', 'let', 'it', 'not', 'be', 'ranked', 'as', 'the', 'least', 'considerable', ',',
'that', 'though', 'sisters', ',', 'and', 'living', 'almost', 'within', 'sight', 'of',
'each', 'other', ',', 'they', 'could', 'live', 'without', 'disagreement', 'between',
'themselves', ',', 'or', 'producing', 'coolness', 'between', 'their', 'husbands', '.',
'THE', 'END']
>>>```
可以通过改变它的索引值来修改链表中的元素。在接下来的例子中,把sent[0]放在等号左侧①。也可以用新内容替换掉整个片段②。最后一个报错的原因是这个链表只有4个元素而要获取4后面的元素,所以产生了错误③。

sent[0] = 'First' ①
sent[9] = 'Last'
len(sent)

10

sent[1:9] = ['Second', 'Third'] ②
sent

['First', 'Second', 'Third', 'Last']

sent[9] ③

Traceback (most recent call last):
 File "", line 1, in ?
IndexError: list index out of range

提示 轮到你来:

定义你的句子,使用前文中的方法修改个别词和词组(切片)。尝试本章结尾关于链表的练习,检验你是否真正理解。
变量
从1.1节开始,已经查看过名为text1,text2等的文本。像这样通过只输入简短的名字来就能引用一本250000字的书的做法节省了很多打字时间。一般情况下,可以对任意的计算命名。在前面的小节中已经这样做了,如下所示,定义一个变量sent1。

>>> sent1 = ['Call', 'me', 'Ishmael', '.']
>>>```
语句形式是:变量 = 表达式。Python通过计算右边的表达式把结果保存在变量中。这个过程被称为赋值。它并不产生任何输出,但只能在新的一行输入变量的名字才能够检查它的内容。等号可能会有些误解,因为信息是从右边流到左边的。你把它想象成一个左箭头可能会有帮助。变量的名字可以是任何你喜欢的名字,如:my_sent、sentence、xyzzy等。变量必须以字母开头,可以包含数字和下划线。下面是变量和赋值的一些例子。

my_sent = ['Bravely', 'bold', 'Sir', 'Robin', ',', 'rode',

...'forth', 'from', 'Camelot', '.']

noun_phrase = my_sent[1:4]
noun_phrase

['bold', 'Sir', 'Robin']

wOrDs = sorted(noun_phrase)
wOrDs

['Robin', 'Sir', 'bold']

请记住,排序表中大写字母出现在小写字母之前。

提示

请注意,在前面的例子中,将my_sent的定义分成两行。Python表达式可以被分割成多行,只要它出现在任何一种括号内。Python使用...提示符表示期望更多的输入。在这些连续的行中有多少缩进都没有关系,因为加入缩进通常会便于阅读。
最好是选择有意义的变量名,它能提醒你代码的含义,也能帮助别人读懂你的Python代码。Python并不理解这些名称的意义。它只是盲目地服从你的指令,如果你输入一些令人困惑的代码,例如:one = 'two'或者two = 3,它也不会反对。唯一的限制是变量名不能是Python的保留字,如def、if、not或import。如果你使用了保留字,Python会产生语法错误。

>>> not = 'Camelot'
File "<stdin>", line 1
  not = 'Camelot'
     ^
SyntaxError: invalid syntax
>>>```
我们经常使用变量来保存计算的中间步骤,尤其是在这样做能够使代码更容易被读懂时。因此,len(set(text1))也可以写作如下形式。

vocab = set(text1)
vocab_size = len(vocab)
vocab_size

19317

提示 注意!

为Python变量选择名称(或标识符)时请注意。首先,应该以字母开始,后面跟数字(0到9)或字母。因此,abc23是正确的,而23abc会导致语法错误。名称是明确区分大小写的。这意味着myVar和myvar是不同的变量。变量名不能包含空格,但可以用下划线把单词分开,如my_var。注意不要插入连字符来代替下划线:my-var不对,因为Python会把-解释为减号。
字符串
一些用来访问链表元素的方法也可以用在单独的词或字符串上。例如可以把一个字符串指定给一个变量①,索引一个字符串②,划分一个字符串③。

>>> name = 'Monty' ①
>>> name[0] ②
'M'
>>> name[:4] ③
'Mont'
>>>```
还可以对字符串执行乘法和加法。

name * 2

'MontyMonty'

name + '!'

'Monty!'

可以把词用链表连接起来组成单个字符串,或者把字符串分割成一个链表,如下面所示。

>>> ' '.join(['Monty', 'Python'])
'Monty Python'
>>> 'Monty Python'.split()
['Monty', 'Python']
>>>```
相关文章
|
10月前
|
数据采集 机器学习/深度学习 自然语言处理
NLP助力非结构化文本抽取:实体关系提取实战
本文介绍了一套基于微博热帖的中文非结构化文本分析系统,通过爬虫代理采集数据,结合NLP技术实现实体识别、关系抽取及情感分析。核心技术包括爬虫模块、请求配置、页面采集和中文NLP处理,最终将数据结构化并保存为CSV文件或生成图谱。代码示例从基础正则规则到高级深度学习模型(如BERT-BiLSTM-CRF)逐步演进,适合初学者与进阶用户调试与扩展,展现了中文NLP在实际场景中的应用价值。
694 3
NLP助力非结构化文本抽取:实体关系提取实战
|
存储 Python
Python 实现单向链表,和单向链表的反转
链表是一种数据结构,每个节点存储相邻节点的位置信息。单链表中的节点仅存储下一节点的位置。通过Python实现单链表,定义`ListNode`类并关联节点可创建链表。例如,创建A-&gt;B-&gt;C的链表后,可通过反转函数`reverse`将链表反转为CBA。代码展示了如何实现和操作单链表。
291 6
Python 实现单向链表,和单向链表的反转
|
11月前
|
存储 Python
Python 中链表的个人理解
简介:本文介绍了Python中链表的基本组成及其操作实现。链表由`head`(头节点)、中间节点和`tail`(尾节点)三部分构成,每个节点通过`Node`类定义,包含`value`(值域)和`next`(指针域)。示例代码展示了链表的增删查功能,包括`add`(头部插入)、`append`(尾部插入)、`remove`(删除节点)、`search`(查找节点)及遍历方法。运行结果验证了链表操作的正确性。
|
存储 算法 搜索推荐
Python 实现反转、合并链表有啥用?
大家好,我是V哥。本文介绍Python实现反转链表和合并链表的应用场景及代码实现。反转链表适用于时间序列数据展示、回文链表判断等;合并链表则用于大规模数据排序、数据库查询结果集合并等。通过迭代和递归方法实现反转链表,以及合并两个或多个有序链表的算法,帮助开发者解决实际问题。关注V哥,了解更多实用编程技巧。 先赞再看后评论,腰缠万贯财进门。
254 0
|
Python
探索 Python 中链表的实现:从基础到高级
链表是一种由节点组成的基础数据结构,每个节点包含数据和指向下一个节点的引用。本文通过Python类实现单向链表,详细介绍了创建、插入、删除节点等操作,并提供示例代码帮助理解。链表在处理动态数据时具有高效性,适用于大量数据变动的场景。文章为初学者提供了全面的入门指南,助你掌握链表的核心概念与应用。
718 0
|
机器学习/深度学习 自然语言处理 知识图谱
GraphRAG在自然语言处理中的应用:从问答系统到文本生成
【10月更文挑战第28天】作为一名自然语言处理(NLP)和图神经网络(GNN)的研究者,我一直在探索如何将GraphRAG(Graph Retrieval-Augmented Generation)模型应用于各种NLP任务。GraphRAG结合了图检索和序列生成技术,能够有效地处理复杂的语言理解和生成任务。本文将从个人角度出发,探讨GraphRAG在构建问答系统、文本摘要、情感分析和自动文本生成等任务中的具体方法和案例研究。
615 5
|
自然语言处理 Python
如何使用自然语言处理库`nltk`进行文本的基本处理
这段Python代码展示了如何使用`nltk`库进行文本的基本处理,包括分词和词频统计。首先需要安装`nltk`库,然后通过`word_tokenize`方法将文本拆分为单词,并使用`FreqDist`类统计每个单词的出现频率。运行代码后,会输出每个词的出现次数,帮助理解文本的结构和常用词。
389 1
|
人工智能 自然语言处理 语音技术
利用Python进行自然语言处理(NLP)
利用Python进行自然语言处理(NLP)
244 1
|
人工智能 自然语言处理 语音技术
利用Python进行自然语言处理(NLP)
利用Python进行自然语言处理(NLP)
371 3
|
自然语言处理 算法 数据挖掘
探讨如何利用Python中的NLP工具,从被动收集到主动分析文本数据的过程
【10月更文挑战第11天】本文介绍了自然语言处理(NLP)在文本分析中的应用,从被动收集到主动分析的过程。通过Python代码示例,详细展示了文本预处理、特征提取、情感分析和主题建模等关键技术,帮助读者理解如何有效利用NLP工具进行文本数据分析。
344 2