• 4.11 练习

    4.11 练习

    1. ☼ 使用 Python 的帮助功能,找出更多关于序列对象的内容。在解释器中输入help(str)help(list)help(tuple)。这会给你一个每种类型支持的函数的完整列表。一些函数名字有些特殊,两侧有下划线;正如帮助文档显示的那样,每个这样的函数对应于一些较为熟悉的东西。例如x.__getitem__(y)仅仅是以长篇大论的方式使用x[y]

    2. ☼ 确定三个同时在元组和链表上都可以执行的操作。确定三个不能在元组上执行的列表操作。命名一段使用列表替代元组会产生一个 Python 错误的代码。

    3. ☼ 找出如何创建一个由单个项目组成的元组。至少有两种方法可以做到这一点。

    4. ☼ 创建一个列表words = ['is', 'NLP', 'fun', '?']。使用一系列赋值语句(如words[1] = words[2])和临时变量tmp将这个列表转换为列表['NLP', 'is', 'fun', '!']。现在,使用元组赋值做相同的转换。

    5. ☼ 通过输入help(cmp)阅读关于内置的比较函数cmp的内容。它与比较运算符在行为上有何不同?

    6. ☼ 创建一个 n-grams 的滑动窗口的方法在下面两种极端情况下是否正确:n = 1 和 n = len(sent)

    7. ☼ 我们指出当空字符串和空链表出现在if从句的条件部分时,它们的判断结果是False。在这种情况下,它们被说成出现在一个布尔上下文中。实验各种不同的布尔上下文中的非布尔表达式,看它们是否被判断为TrueFalse

    8. ☼ 使用不等号比较字符串,如'Monty' < 'Python'。当你做'Z' < 'a'时会发生什么?尝试具有共同前缀的字符串对,如'Monty' < 'Montague'。阅读有关“字典排序”的内容以便了解这里发生了什么事。尝试比较结构化对象,如('Monty', 1) < ('Monty', 2)。这与预期一样吗?

    9. ☼ 写代码删除字符串开头和结尾处的空白,并规范化词之间的空格为一个单独的空格字符。

      1. 使用split()join()做这个任务
      2. 使用正则表达式替换做这个任务
    10. ☼ 写一个程序按长度对词排序。定义一个辅助函数cmp_len,它在词长上使用cmp比较函数。

    11. ◑ 创建一个词列表并将其存储在变量sent1。现在赋值sent2 = sent1。修改sent1中的一个项目,验证sent2改变了。

      1. 现在尝试同样的练习,但使用sent2 = sent1[:]赋值。再次修改sent1看看sent2会发生什么。解释。
      2. 现在定义text1为一个字符串列表的列表(例如表示由多个句子组成的文本)。现在赋值text2 = text1[:],分配一个新值给其中一个词,例如text1[1][1] = 'Monty'。检查这对text2做了什么。解释。
      3. 导入 Python 的deepcopy()函数(即from copy import deepcopy),查询其文档,使用它生成任一对象的新副本。
    12. ◑ 使用列表乘法初始化 n-by-m 的空字符串列表的咧表,例如word_table = [[''] * n] * m。当你设置其中一个值时会发生什么事,例如word_table[1][2] = "hello"?解释为什么会出现这种情况。现在写一个表达式,使用range()构造一个列表,表明它没有这个问题。

    13. ◑ 写代码初始化一个称为word_vowels的二维数组的集合,处理一个词列表,添加每个词到word_vowels[l][v],其中l是词的长度,v是它包含的元音的数量。

    14. ◑ 写一个函数novel10(text)输出所有在一个文本最后 10%出现而之前没有遇到过的词。

    15. ◑ 写一个程序将一个句子表示成一个单独的字符串,分割和计数其中的词。让它输出每一个词和词的频率,每行一个,按字母顺序排列。

    16. ◑ 阅读有关 Gematria 的内容,它是一种方法,分配一个数字给词汇,具有相同数字的词之间映射以发现文本隐藏的含义(http://en.wikipedia.org/wiki/Gematria, http://essenes.net/gemcal.htm)。

      1. 写一个函数gematria(),根据letter_vals中的字母值,累加一个词的字母的数值:

        1. >>> letter_vals = {'a':1, 'b':2, 'c':3, 'd':4, 'e':5, 'f':80, 'g':3, 'h':8,
        2. ... 'i':10, 'j':10, 'k':20, 'l':30, 'm':40, 'n':50, 'o':70, 'p':80, 'q':100,
        3. ... 'r':200, 's':300, 't':400, 'u':6, 'v':6, 'w':800, 'x':60, 'y':10, 'z':7}
      2. 处理一个语料库(nltk.corpus.state_union)对每个文档计数它有多少词的字母数值为 666。

      3. 写一个函数decode()来处理文本,随机替换词汇为它们的 Gematria 等值的词,以发现文本的“隐藏的含义”。

    17. ◑ 写一个函数shorten(text, n)处理文本,省略文本中前 n 个最频繁出现的词。它的可读性会如何?

    18. ◑ 写代码输出词汇的索引,允许别人根据其含义查找词汇(或它们的发言;词汇条目中包含的任何属性)。

    19. ◑ 写一个列表推导排序 WordNet 中与给定同义词集接近的同义词集的列表。例如,给定同义词集minke_whale.n.01, orca.n.01, novel.n.01tortoise.n.01,按照它们与right_whale.n.01shortest_path_distance()对它们进行排序。

    20. ◑ 写一个函数处理一个词列表(含重复项),返回一个按照频率递减排序的词列表(没有重复项)。例如如果输入列表中包含词table的 10 个实例,chair的 9 个实例,那么在输出列表中table会出现在chair前面。

    21. ◑ 写一个函数以一个文本和一个词汇表作为它的参数,返回在文本中出现但不在词汇表中的一组词。两个参数都可以表示为字符串列表。你能使用set.difference()在一行代码中做这些吗?

    22. ◑ 从 Python 标准库的operator模块导入itemgetter()函数(即from operator import itemgetter)。创建一个包含几个词的列表words。现在尝试调用:sorted(words, key=itemgetter(1))sorted(words, key=itemgetter(-1))。解释itemgetter()正在做什么。

    23. ◑ 写一个递归函数lookup(trie, key)在查找树中查找一个关键字,返回找到的值。扩展这个函数,当一个词由其前缀唯一确定时返回这个词(例如vanguard是以vang-开头的唯一的词,所以lookup(trie, 'vang')应该返回与lookup(trie, 'vanguard')相同的内容)。

    24. ◑ 阅读关于“关键字联动”的内容((Scott & Tribble, 2006)的第 5 章)。从 NLTK 的莎士比亚语料库中提取关键字,使用 NetworkX 包,画出关键字联动网络。

    25. ◑ 阅读有关字符串编辑距离和 Levenshtein 算法的内容。尝试nltk.edit_distance()提供的实现。这用的是动态规划的何种方式?它使用的是自下而上还是自上而下的方法?[另见http://norvig.com/spell-correct.html]

    26. ◑ Catalan 数出现在组合数学的许多应用中,包括解析树的计数(6)。该级数可以定义如下:C<sub>0</sub> = 1, and C<sub>n+1</sub> = Σ<sub>0..n</sub> (C<sub>i</sub>C<sub>n-i</sub>)。

      1. 编写一个递归函数计算第 n 个 Catalan 数 C<sub>n</sub>。
      2. 现在写另一个函数使用动态规划做这个计算。
      3. 使用timeit模块比较当 n 增加时这些函数的性能。
    27. ★ 重现有关著作权鉴定的(Zhao & Zobel, 2007)中的一些结果。

    28. ★ 研究性别特异词汇选择,看你是否可以重现一些http://www.clintoneast.com/articles/words.php的结果

    29. ★ 写一个递归函数漂亮的按字母顺序排列输出一个查找树,例如:

      1. chair: 'flesh'
      2. ---t: 'cat'
      3. --ic: 'stylish'
      4. ---en: 'dog'