2019年3月6日 星期三

[Python] Generator 迭代產生器

Generator 迭代產生器


Generator

 #Benefits - Memory Usage
 
# 利用 list 迭代
range_num = 10
for i in [x*x for x in range(range_num)]:
    # do something
    pass
# 利用 generator 迭代
for i in (x*x for x in range(range_num)):
    # do something
    pass


 #Memory Usage - by using generator
 
import psutil
before_used = psutil.virtual_memory().used # expressed in bytes
after_used = 0
print("before:", before_used) ## 10458206208
range_num = 1000000
for i in (x*x for x in range(range_num)): # 第二種方法:對 generator 進行迭代
    if i == (range_num - 1) * (range_num - 1):
        after_used = psutil.virtual_memory().used
        print("after:", after_used)## 10461298688 
print("used memory:", (after_used - before_used)) ## 3092480

Module - os

 
import os
    
# 顯示絕對路徑
os.path.abspath("session_1-ans.ipynb") # '/Users/felix/Python/session_1-ans.ipynb'

# 將多個字串組合為路徑
'/'.join(['path', 'result', 'a.csv']) # 'path/result/a.csv'

# 將多個字串組合為路徑
os.path.join('path', 'result', 'a.csv') # 'path/result/a.csv'

# 檢查某路徑/資料夾是否存在
os.path.exists("python\session_1-ans.ipynb") # False

Q1: 若某 k 位數的正整數,其所有位數數字的 k 次方和等於該數相等,則稱為阿姆斯壯數(Armstrong number)。 例如 1^3 + 5^3 + 3^3 = 153, 則 153 是一個阿姆斯壯數。 請創建一個 Generator 函式,找出 100 ~ 999 的所有三位數的阿姆斯壯數; 利用 yield 回傳數值,並且用多次呼叫此 Generator 函式,依序列印出所找到的阿姆斯壯數。
def armstrong_number():
    for num in range(100, 1000):
        temp = num
        sum = 0
        while temp > 0:          
            digit = temp % 10    # 取餘數 取得當前 temp 的個位數
            sum += digit ** 3    # 當前取得的位數 的三次方加入 sum
            temp //= 10          # 將當前 temp 往右位移一位 (以10為底 所以除10)
        
        if sum == num:           # 如果 所有位數的3次方 和 等於該數
            yield sum            # 返回 此阿姆斯壯數
            
a = armstrong_number()

try:
    while(True):
        print(a.__next__())
except StopIteration:
    print("The End")
Q2: 透過 Generators 讀取一個純文字檔案 (Optional) hint 1. 利用 open("your_file_path", ""r) 來開啟檔案 hint 2. 需設定每次要讀取檔案的大小 hint 3. 利用迴圈存取,直到檔案讀取完畢為止
# Q2.
def read_in_block(file_path):  
    BLOCK_SIZE = 1024  
    with open(file_path, "r") as f:  
        while True:  
            block = f.read(BLOCK_SIZE)  # 每次讀取固定長度到記憶體  
            if block:  
                yield block  
            else: 
                f.close()
                return 
            
def batch_read():  
    file_path = "input_your_file_path"  # 輸入檔案的路徑 
    for block in read_in_block(file_path):  
        # do something
        print(block)

沒有留言:

張貼留言