iT邦幫忙

2024 iThome 鐵人賽

DAY 15
1
自我挑戰組

每日挑戰:從零開始的 Python 學習之旅系列 第 15

【Day 15】基礎語法 - 函數進階篇 - 續集

  • 分享至 

  • xImage
  •  

Hi 大家好,

今天要開始介紹基礎語法中的函數進階篇之續集,那我們開始吧!

產生器(Generator)

產生器的概念

Q: 什麼是產生器?
A: 是Python的一種特別的設計,會回傳一個物件,可以從物件中逐步的取出值,而不是一次性的取到所有的值

生成器可以透過兩種方式建立

  • ()小括號中寫推導式,但這不會是一個元組(Tuple),Tuple沒有推導式
  • 產生器是屬於惰性計算(lazy evaluation)的一種形式
numbers = (n for n in range(0, 10))
print(numbers)
print(list(numbers))
PS D:\Project\practice> python hi.py
<generator object <genexpr> at 0x00000207C1F9C700>
[0, 1, 2, 3, 4, 5, 6, 7, 8, 9]
PS D:\Project\practice>
  • 在函數中使用yeild關鍵字
def even_numbers(n):
    i = 1
    while i <= n:
        if i % 2 == 0:
            yield i # 跑到這裡會先停住,一開始會是2,除非有人來拿,才會再丟出去
        i += 1
    
nn = even_numbers(10)
PS D:\Project\practice> python -i hi.py
>>> print(en)
<generator object even_numbers at 0x00000217E37AF1C0>
>>>

產生器的操作

  • 當產生一個產生器numbers時,可以使用next(numbers)函數來取得產生器的資料,再執行一次可以取得下一筆資料,如果使用list()函數可以把剩餘的資料全部列印出來。
  • 這裡要特別注意,只要是有印出來的資料,就等於是會從產生器中移除,當印出所有資料後,等於產生器內沒有資料可以再取得,這時候再使用next()函數時候,會發生錯誤,而使用list()函數會得到空的串列

[情境一]

>>> numbers = (n for n in range(0, 10))
>>> print(numbers) 
<generator object <genexpr> at 0x0000019D8771F400>
>>> next(numbers)    <==== 每次執行只會取得一筆資料
0
>>> next(numbers)
1
>>> next(numbers)
2
>>> list(numbers)
[3, 4, 5, 6, 7, 8, 9]    <==== 一次列印出所有剩餘的資料
>>> next(numbers)
Traceback (most recent call last):   <====  因為產生器內已經沒有資料,所以取不到東西,發生錯誤
  File "<stdin>", line 1, in <module>
StopIteration
>>> list(numbers)   <====  因為產生器內已經沒有資料,所以會是空串列
[]
>>>

[情境二]

def even_numbers(n):
    i = 1
    while i <= n:
        if i % 2 == 0:
            yield i     # 跑到這裡會先停住,一開始會是2,除非有人來拿,d才會再丟出去
        i += 1
    
en = even_numbers(10)
PS D:\Project\practice> python -i hi.py
>>> print(en)
<generator object even_numbers at 0x00000220199CF1C0>
>>> next(en)
2
>>> next(en)
4
>>> list(en)
[6, 8, 10]
>>> next(en) 
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
StopIteration
>>> list(en)  
[]
>>>

遞迴函數

Q: 什麼是遞迴函數?
A: 簡單來說就是自己呼叫自己

費波那契數為例:
定義為數列的每一項都是前兩項之和, F(n) = F(n-1) + F(n-2),其中 n >= 2

# fib
def fib(n):
    if n == 0:
        return 0
    if n == 1:
        return 1
    
    return fib(n-1) + fib(n - 2)

print(fib(5))
PS D:\Project\practice> python hi.py   
5
PS D:\Project\practice>

使用上要特別注意的事項:

  • 要清楚的設定判斷條件,避免進入無窮迴圈
  • 某些遞迴演算法可能會造成性能負載過重
  • Python有遞迴深度限制(默認約為 1000 層),一旦出現無窮迴圈情況,Python會拋出RecursionError例外
def foo():
    foo()

foo()
PS D:\Project\practice> python hi.py
Traceback (most recent call last):
  File "D:\Project\practice\hi.py", line 4, in <module>
    foo()
  File "D:\Project\practice\hi.py", line 2, in foo
    foo()
  File "D:\Project\practice\hi.py", line 2, in foo
    foo()
  File "D:\Project\practice\hi.py", line 2, in foo
    foo()
  [Previous line repeated 996 more times]
RecursionError: maximum recursion depth exceeded
PS D:\Project\practice>

那今天就介紹到這裡,我們明天見~


上一篇
【Day 14】基礎語法 - 函數進階篇 - 續集
下一篇
【Day 16】基礎語法 - 函數進階篇 - 續集
系列文
每日挑戰:從零開始的 Python 學習之旅30
圖片
  直播研討會
圖片
{{ item.channelVendor }} {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

尚未有邦友留言

立即登入留言