Python中級篇—高級數(shù)據(jù)類型(集合和命名元組迭代器和生成器)
集合 (Set)
集合是一種無序、可變、且元素唯一的數(shù)據(jù)結構。在 Python 中,可以通過 set() 函數(shù)或使用大括號 {} 來創(chuàng)建一個集合。
創(chuàng)建集合
# 創(chuàng)建一個空集合
empty_set = set()
print(empty_set)
# 創(chuàng)建帶有初始元素的集合
numbers = {1, 2, 3, 4, 5}
print(numbers)
輸出:
set()
{1, 2, 3, 4, 5}
注意,如果使用大括號創(chuàng)建一個空集合,會得到一個空字典而不是空集合。所以,創(chuàng)建空集合時應該使用 set() 函數(shù)。
集合的基本操作
添加元素
可以使用 add() 方法向集合中添加元素,如果添加的元素已經存在于集合中,則不會有任何影響。
fruits = {'apple', 'banana', 'orange'}
fruits.add('grape')
fruits.add('apple') # 不會有任何影響,因為'apple'已經存在于集合中
print(fruits)
輸出:
{'banana', 'grape', 'apple', 'orange'}
刪除元素
可以使用 remove() 或 discard() 方法從集合中刪除指定元素,如果元素不存在,則 remove() 方法會拋出 KeyError 異常,而 discard() 方法不會有任何影響。
fruits = {'apple', 'banana', 'orange'}
fruits.remove('banana')
print(fruits)
fruits.discard('watermelon') # 不會有任何影響,因為'watermelon'不存在于集合中
print(fruits)
輸出:
{'apple', 'orange'}
{'apple', 'orange'}
集合運算
可以對集合執(zhí)行交集、并集、差集、對稱差等運算。
A = {1, 2, 3, 4, 5}
B = {4, 5, 6, 7, 8}
print(A & B) # 交集
print(A | B) # 并集
print(A - B) # 差集
print(A ^ B) # 對稱差
輸出:
{4, 5}
{1, 2, 3, 4, 5, 6, 7, 8}
{1, 2, 3}
{1, 2, 3, 6, 7, 8}
代碼演示
# 創(chuàng)建一個空集合
empty_set = set()
print(empty_set)
# 創(chuàng)建帶有初始元素的集合
numbers = {1, 2, 3, 4, 5}
print(numbers)
# 添加元素
fruits = {'apple', 'banana', 'orange'}
fruits.add('grape')
fruits.add('apple') # 不會有任何影響,因為'apple'已經存在于集合中
print(fruits)
# 刪除元素
fruits.remove('banana')
print(fruits)
fruits.discard('watermelon') # 不會有任何影響,因為'watermelon'不存在于集合中
print(fruits)
# 集合運算
A = {1, 2, 3, 4, 5}
B = {4, 5, 6, 7, 8}
print(A & B) # 交集
print(A | B) # 并集
print(A - B) # 差集
print(A ^ B) # 對稱差
輸出:
set()
{1, 2, 3, 4, 5}
{'orange', 'banana', 'grape', 'apple'}
{'orange', 'grape', 'apple'}
{'orange', 'grape', 'apple'}
{4, 5}
{1, 2, 3, 4, 5, 6, 7, 8}
{1, 2, 3}
{1, 2, 3, 6, 7, 8}
命名元組 (NamedTuple)
命名元組是一種具名元素的元組。與普通元組不同,命名元組的每個元素都有一個可讀性更高的名稱。在 Python 中,可以通過 collections 模塊中的 namedtuple() 函數(shù)來創(chuàng)建一個命名元組。
創(chuàng)建命名元組
創(chuàng)建命名元組時需要指定元素的名稱和順序,可以使用逗號分隔的字符串或者是元素名稱組成的列表來定義。
from collections import namedtuple
# 用逗號分隔的字符串定義元素
Person = namedtuple('Person', 'name age gender')
p1 = Person('Bob', 25, 'male')
print(p1)
# 使用元素名稱組成的列表定義元素
Point = namedtuple('Point', ['x', 'y'])
p2 = Point(3.14, 2.71)
print(p2)
輸出:
Person(name='Bob', age=25, gender='male')
Point(x=3.14, y=2.71)
訪問命名元組
可以使用點號運算符來訪問命名元組中的元素。
print(p1.name)
print(p2.y)
輸出:
Bob
2.71
修改命名元組
命名元組是不可變的,因此不能直接修改其元素。但可以使用 _replace() 方法創(chuàng)建一個新的命名元組,該方法會返回一個新的命名元組,其中指定的元素會被替換為新的值。注意,_replace() 方法并不會改變原來的命名元組,而是返回一個新的命名元組。
p3 = p2._replace(y=42)
print(p2)
print(p3)
輸出:
Point(x=3.14, y=2.71)
Point(x=3.14, y=42)
迭代器和生成器
迭代器和生成器是 Python 中非常重要的概念,它們可以幫助我們有效地處理大量數(shù)據(jù),避免內存溢出的問題。
迭代器 (Iterator)
迭代器是一種可以逐個訪問集合元素的對象,而不必將集合完全加載到內存中。迭代器對象從第一個元素開始訪問,直到所有元素都被訪問完為止。在 Python 中,可以使用 iter() 和 next() 函數(shù)來創(chuàng)建和訪問迭代器。
numbers = [1, 2, 3, 4, 5]
it = iter(numbers)
print(next(it))
print(next(it))
print(next(it))
print(next(it))
print(next(it))
輸出:
1
2
3
4
5
生成器 (Generator)
生成器是一種特殊的迭代器,可以使用函數(shù)來創(chuàng)建。與普通函數(shù)不同,生成器函數(shù)返回的是一個迭代器對象,可以使用 yield 關鍵字來逐個返回值,而不是一次性返回所有值。
def square_numbers(n):
for i in range(n):
yield i ** 2
# 創(chuàng)建生成器對象
my_generator = square_numbers(5)
# 訪問生成器中的元素
print(next(my_generator))
print(next(my_generator))
print(next(my_generator))
print(next(my_generator))
print(next(my_generator))
輸出:
0
1
4
9
16
生成器的一個重要特點是可以節(jié)省內存,因為它不需要將所有元素保存在內存中,而是逐個生成元素。此外,生成器還可以實現(xiàn)無限序列的生成,比如生成所有的斐波那契數(shù)列元素。以下是一個生成斐波那契數(shù)列的生成器函數(shù)示例:
def fibonacci():
a, b = 0, 1
while True:
yield a
a, b = b, a + b
# 創(chuàng)建生成器對象
my_generator = fibonacci()
# 訪問生成器中的元素
print(next(my_generator))
print(next(my_generator))
print(next(my_generator))
print(next(my_generator))
print(next(my_generator))
print(next(my_generator))
輸出:
0
1
1
2
3
5
除了使用 next() 函數(shù)來訪問生成器中的元素之外,我們還可以使用 for 循環(huán)來遍歷生成器中的所有元素,因為生成器也是一種可迭代對象。
# 創(chuàng)建生成器對象
my_generator = square_numbers(5)
# 遍歷生成器中的元素
for num in my_generator:
print(num)
輸出:
0
1
4
9
16
另外一個有用的函數(shù)是 send(),它可以在調用生成器函數(shù)時向生成器中傳遞一個值,并從當前位置繼續(xù)執(zhí)行生成器函數(shù)。具體來說,send() 函數(shù)會將傳遞的值作為 yield 表達式的返回值,并將生成器函數(shù)的執(zhí)行從 yield 表達式后的下一條語句開始執(zhí)行。以下是一個示例:
def square_numbers():
num = 0
while True:
# 從外部接收一個值
x = yield num ** 2
if x is not None:
num = x
else:
num += 1
# 創(chuàng)建生成器對象
my_generator = square_numbers()
# 訪問生成器中的元素,并向生成器中傳遞一個值
print(next(my_generator))
print(next(my_generator))
print(my_generator.send(5))
print(next(my_generator))
輸出:
0
1
25
36
在上面的示例中,我們定義了一個生成器函數(shù) square_numbers(),它會不斷地生成平方數(shù)。在函數(shù)中,我們使用 yield 表達式來逐個返回平方數(shù),并將 num 的初始值設置為 0。當從外部通過 send() 函數(shù)向生成器中傳遞一個值時,我們可以在函數(shù)中將 num 的值修改為傳遞的值,并從 yield 表達式后的下一條語句開始執(zhí)行。
以上就是迭代器和生成器的基本介紹,它們是 Python 中非常重要的概念,可以幫助我們高效地處理大量數(shù)據(jù)。