24/9/21 python的推導式、生成器

Gold_stein發表於2024-09-21

python推導式和生成器

介紹

1. 列表推導式(List Comprehension)

列表推導式是最常見的一種推導式,它允許你用一行程式碼生成列表,形式如下:

new_list = [expression for item in iterable if condition]
  • expression:要新增到新列表的值,可以是簡單的變數,也可以是運算結果。
  • item:來自迭代物件的每個元素。
  • iterable:任何可迭代物件(如列表、字串、range 等)。
  • if condition:可選,用來篩選符合條件的元素。

示例:

生成一個包含平方數的列表:

squares = [x**2 for x in range(10)]
print(squares)  # 輸出 [0, 1, 4, 9, 16, 25, 36, 49, 64, 81]

2. 字典推導式(Dictionary Comprehension)

字典推導式與列表推導式類似,只不過它生成的是字典,格式如下:

new_dict = {key: value for item in iterable}

示例:

生成一個鍵為數字,值為其平方的字典:

squares_dict = {x: x**2 for x in range(5)}
print(squares_dict)  # 輸出 {0: 0, 1: 1, 2: 4, 3: 9, 4: 16}

3. 集合推導式(Set Comprehension)

集合推導式的語法與列表推導式類似,但生成的結果是集合。

new_set = {expression for item in iterable if condition}

示例:

生成一個不重複的平方數集合:

squares_set = {x**2 for x in range(5)}
print(squares_set)  # 輸出 {0, 1, 4, 9, 16}

4. 生成器表示式(Generator Expression)

生成器表示式和列表推導式類似,但它不直接生成列表,而是返回一個生成器物件,用於惰性求值,適合處理大量資料。

gen = (x**2 for x in range(10))
print(list(gen))  # 輸出 [0, 1, 4, 9, 16, 25, 36, 49, 64, 81]

5. 巢狀推導式

推導式也可以巢狀,用於生成複雜的結構。

示例:

生成一個二維列表:

matrix = [[i * j for j in range(3)] for i in range(3)]
print(matrix)  # 輸出 [[0, 0, 0], [0, 1, 2], [0, 2, 4]]

總結:

推導式使程式碼更加簡潔、可讀,並且在處理生成列表、字典或集合時特別高效。不過,推導式過於複雜時可能會影響程式碼的可讀性,需謹慎使用。

1. 什麼是生成器?

生成器(Generator) 是 Python 中一種特殊型別的迭代器,用於生成一系列的值。在常規的函式中,使用 return 來返回值並結束函式,而在生成器中,使用 yield 來逐次生成值,而不終止函式。生成器可以暫停函式的執行,並在下一次迭代時恢復執行,這種特性使得它適用於處理大量資料或無限資料流。

生成器的定義:

  • 生成器可以透過生成器函式建立,使用 yield 語句。
  • 生成器也可以透過生成器表示式建立,類似於列表推導式,但使用圓括號代替方括號。

生成器函式示例:

def my_generator():
    yield 1
    yield 2
    yield 3

gen = my_generator()
for value in gen:
    print(value)

2. 生成器與列表的區別

  • 記憶體佔用

    • 生成器是惰性求值的,這意味著它們不會一次性把所有的值載入到記憶體中,而是每次需要時才生成下一個值,因此非常節省記憶體。
    • 列表則會在建立時一次性將所有元素載入到記憶體中,尤其是當資料量很大時,可能導致大量的記憶體佔用。
  • 求值方式

    • 生成器是惰性求值的(即在需要時才生成下一個值),而列表是即時求值的(一次性生成整個列表的所有值)。
  • 可重複使用

    • 生成器一旦迭代完畢,就不能再次使用,除非重新建立。
    • 列表可以多次迭代,因為它們的所有元素都儲存在記憶體中。

列表與生成器的對比:

# 列表
lst = [x**2 for x in range(5)]
print(lst)  # 輸出: [0, 1, 4, 9, 16]

# 生成器
gen = (x**2 for x in range(5))
print(list(gen))  # 輸出: [0, 1, 4, 9, 16]

生成器不佔用大量記憶體,但在將生成器轉換為列表時,才會將所有值儲存在記憶體中。

3. 什麼是惰性求值?

惰性求值(Lazy Evaluation),也叫延遲求值,是一種計算策略,指的是當值真正被需要時才進行計算,而不是在定義時立即計算。這使得生成器可以在處理大量資料或無限序列時顯得特別高效。

惰性求值的好處:

  • 節省記憶體:生成器不會立即生成所有元素,只在迭代到某個值時才計算它,因此適合處理大規模或無限資料流。
  • 提高效率:透過按需生成資料,避免了不必要的計算和記憶體佔用。

示例:

def count_up_to(n):
    count = 1
    while count <= n:
        yield count
        count += 1

counter = count_up_to(5)
print(next(counter))  # 1
print(next(counter))  # 2
# 生成器不會計算後續的值,直到你需要它們為止

在此例中,生成器在呼叫 next() 時才生成下一個值,未被呼叫時不會生成,因此更高效。

總結:

  • 生成器是惰性求值的迭代器,用來節省記憶體並延遲計算。
  • 列表是立即求值的,它會一次性載入所有元素。
  • 惰性求值是指在需要時才進行計算,而不是立即執行,從而提高效能和記憶體使用效率。

生成器特別適用於大規模或無限序列的處理場景,因為它們僅在需要時生成資料,非常節省記憶體。

相關文章