亚洲在线久爱草,狠狠天天香蕉网,天天搞日日干久草,伊人亚洲日本欧美

Python 中的生成器趣味實踐

1. 遍歷文本文件中的單詞

假設存在文本文件 test.txt,內容如下:

The Zen of Python

Beautiful is better than ugly

Simple is better than complex

注意文件包含有空行,要求完成如下任務:

  1. 統計文件有多少個單詞
  2. 統計文件中每個單詞出現的頻率

2. 直接遍歷的方法

請參考詞條 “Python 中的迭代器趣味實踐” 的第 2 小節,通過直接遍歷文件中單詞的方式實現 “統計單詞的個數” 和 “統計單詞的出現頻率”。

2.1 優點

直接遍歷的方式的優點在于代碼簡單,框架代碼如下:

file = open('test.txt')

while True:
    line = file.readline()
    if not line:
        break

    words = line.split() 
    for word in words:
        處理 word
  • 在第 4 行,讀取文件的每一行
  • 在第 8 行,將文件的一行分割為多個單詞
  • 在第 10 行,對當前正在遍歷的單詞進行處理

2.2 缺點

直接遍歷的方式的缺點在于代碼重復,實現 “統計單詞個數” 和 “統計單詞出現頻率” 這兩個功能需求時,遍歷單詞的框架代碼是重復的。

3. 基于迭代器的方法

請參考詞條 “Python 中的迭代器趣味實踐” 的第 3 小節和第 4 小節,通過基于迭代器的方式實現 “統計單詞的個數” 和 “統計單詞的出現頻率”。

3.1 優點

使用迭代器的方式的優點在于遍歷單詞的代碼簡單,使用如下代碼:

for word in IterateWord(file):
    處理 word

即可對文件中所有的單詞進行遍歷。

3.2 缺點

使用迭代器的方式的缺點在于迭代器的實現較為復雜,相比之下,直接遍歷的框架代碼則非常簡單直觀。在下面的小節中,我們基于生成器簡化迭代器的實現。

4. 基于生成器的方法

4.1 實現生成器

本小節使用生成器實現遍歷文件中所有的單詞,代碼如下:

def generateWord(file):
    while True:
        line = file.readline()
        if not line:
            break

        words = line.split() 
        for word in words:
            yield word         
  • 在第 1 行,定義生成器函數 generateWord,遍歷文件 file 中的單詞
  • 在第 3 行,讀取文件的一行
    • 在第 4 行,如果 not line 為真,則表示讀取文件結束,使用 break 退出
  • 在第 7 行,把 line 切割為多個單詞
  • 在第 8 行,遍歷列表 words
    • 在第 9 行,使用 yield 關鍵字返回當前正在遍歷的單詞

4.2 統計單詞的個數

file = open('test.txt')

count = 0
for word in generateWord(file):
    print(word)
    count = count + 1
  • 在第 1 行,打開文件 test.txt
  • 在第 2 行,變量 count 用于記錄文件中單詞的個數
  • 在第 4 行,遍歷文件中的每一個單詞
    • 在第 5 行,打印當前遍歷的單詞
    • 在第 6 行,統計單詞個數

程序運行輸出結果如下:

The
Zen
of
Python
Beautiful
is
better
than
ugly
Simple
is
better
than
complex
count = 14

4.3 統計單詞的出現頻率

file = open('test.txt')
dict = {}

for word in generateWord(file):
    if word in dict:
        dict[word] += 1
    else:
        dict[word] = 1

for word,count in dict.items():
    print('%s: %d' % (word, count)) 
  • 在第 1 行,打開文件 test.txt,變量 file 標識已經打開的文件
  • 在第 4 行,遍歷每一行文本的單詞
    • 在第 5 行,如果 word 已經存在于 dict 中
      • 則在第 5 行,該單詞出現的次數加 1
    • 在第 7 行,如果 word 不存在于 dict 中
      • 則在第 8 行,該單詞出現的次數初始化為 1
  • 在第 10 行,打印 dict 的鍵和值

程序運行輸出結果如下:

The: 1
Zen: 1
of: 1
Python: 1
Beautiful: 1
is: 2
better: 2
than: 2
ugly: 1
Simple: 1
complex: 1

結果表明:

  • 單詞 is better than 出現了 2 次
  • 其它單詞出現了 1 次

4.4 總結

與 “直接遍歷” 和 “通過迭代器遍歷” 這兩種方式相比,基于生成器的方法由如下優點:

4.4.1 實現生成器簡單

實現生成器的函數 generateWord 的邏輯簡單直觀,代碼如下:

def generateWord(file):
    while True:
        line = file.readline()
        if not line:
            break

        words = line.split() 
        for word in words:
            yield word         
  • 首先,函數依次讀取文件的每一行
  • 然后,再把讀取的行切割成單詞
  • 最后,遍歷單詞

4.4.2 使用生成器簡單

通過 for 循環即可遍歷文件中的單詞,generateWord 隱藏了各種實現細節,代碼如下:

for word in generateWord(file):
    處理 word