什麼是容器?

為什麼需要容器?

想象一下:如果你只有一個蘋果,直接拿在手裏就行;但如果你有一堆蘋果,就需要一個袋子或籃子來裝它們。

Python 中的數據也是如此:

  • 當你只有一個數字(比如3)、一個字符串(比如"hello")時,直接用變量存就行
  • 但當你有一組相關的數據(比如全班同學的名字、一個月的氣温數據)時,就需要用"容器"來統一管理這些數據,方便操作(比如遍歷、查找、添加等)

什麼是容器?

簡單説,能同時裝多個數據的東西,就是容器

Python 中最常見的容器有:

  1. 列表(list):用[]表示,比如[1, 2, 3],像個有序的"抽屜",可以隨時添加/刪除東西
  2. 元組(tuple):用()表示,比如(1, 2, 3),像個封死的"盒子",裏面的東西不能改
  3. 字典(dict):用{}表示,比如{"name": "小明", "age": 18},像個帶標籤的"儲物櫃",每個東西都有自己的名字(鍵)
  4. 集合(set):用{}表示,比如{1, 2, 3},像個無序的"筐",裏面不能有重複的東西

1. 字符串內存模型

變量是最不穩定的,存儲在棧中。

局部變量的引用關係通常存儲在棧中,而變量的不穩定性(生命週期短、隨函數調用動態創建銷燬)與棧內存的特性高度匹配

字符串用的最多,存儲在常量區。

結論:字符串數據不能更改,是不可變數據

2. 整數內存模型

對於小於-5或大於256的整數,Python 不會預先緩存,而是在每次創建時動態分配內存(存儲在堆區)。即使兩個大整數的值相同,它們也會被視為不同的對象,佔用不同的內存地址。

小整數(-5 到 256)

  • 這些整數被緩存並在整個程序中重複使用
  • 它們存儲在特殊的小整數池中,而不是堆內存中

常規整數

  • 對於大多數系統,常規整數是32位或64位
  • 這些整數直接存儲在對象的內存空間中(通常在棧上)

大整數(超出系統字長)

  • 當整數太大無法放入單個機器字時,Python 會在堆內存中分配空間
  • 這些整數使用可變長度的數據結構存儲
  • 每個大整數對象包含:
  • 引用計數
  • 類型信息
  • 實際數值數據(以數組形式存儲)

列表(List)

什麼是列表?

列表(List)是 Python 中最基本、最常用的數據結構之一。它是一個有序可變的元素集合,可以包含任何類型的對象,甚至可以是混合類型。

列表的基本特性

  1. 有序性:列表中的元素按特定順序排列
  2. 可變性:可以修改列表的內容(增刪改)
  3. 異構性:可以包含不同類型的元素
  4. 可嵌套:列表中可以包含其他列表(嵌套列表)
  5. 可迭代:可以使用循環遍歷列表中的元素

創建列表

使用方括號創建
# 空列表
empty_list = []

# 整數列表
numbers = [1, 2, 3, 4, 5]

# 字符串列表
fruits = ["apple", "banana", "cherry"]

# 混合類型列表
mixed = [1, "hello", 3.14, True]

# 嵌套列表
matrix = [[1, 2, 3], [4, 5, 6], [7, 8, 9]]
使用 list() 函數創建
# 從字符串創建列表
chars = list("hello")  # ['h', 'e', 'l', 'l', 'o']

# 從元組創建列表
tuple_to_list = list((1, 2, 3))  # [1, 2, 3]

# 從範圍創建列表
numbers = list(range(5))  # [0, 1, 2, 3, 4]

訪問列表元素

使用索引訪問
fruits = ["apple", "banana", "cherry", "date", "elderberry"]

# 正向索引(從0開始)
print(fruits[0])   # apple
print(fruits[2])   # cherry

# 負向索引(從-1開始)
print(fruits[-1])  # elderberry
print(fruits[-3])  # cherry
使用切片訪問
fruits = ["apple", "banana", "cherry", "date", "elderberry"]

# 基本切片:list[start:stop:step]
print(fruits[1:4])    # ['banana', 'cherry', 'date']
print(fruits[:3])     # ['apple', 'banana', 'cherry'] (從開始到索引2)
print(fruits[2:])     # ['cherry', 'date', 'elderberry'] (從索引2到結束)
print(fruits[::2])    # ['apple', 'cherry', 'elderberry'] (每隔一個元素)
print(fruits[::-1])   # ['elderberry', 'date', 'cherry', 'banana', 'apple'] (反轉列表)

修改列表元素

直接賦值修改
fruits = ["apple", "banana", "cherry"]
fruits[1] = "blueberry"
print(fruits)  # ['apple', 'blueberry', 'cherry']
使用切片修改
numbers = [1, 2, 3, 4, 5]
numbers[1:4] = [20, 30, 40]  # 替換索引1到3的元素
print(numbers)  # [1, 20, 30, 40, 5]

# 插入元素
numbers[2:2] = [25, 26]  # 在索引2處插入元素
print(numbers)  # [1, 20, 25, 26, 30, 40, 5]

# 刪除元素
numbers[1:3] = []  # 刪除索引1到2的元素
print(numbers)  # [1, 26, 30, 40, 5]

列表操作

連接列表
list1 = [1, 2, 3]
list2 = [4, 5, 6]

# 使用 + 運算符
combined = list1 + list2  # [1, 2, 3, 4, 5, 6]

# 使用 extend() 方法
list1.extend(list2)  # list1 變為 [1, 2, 3, 4, 5, 6]
重複列表
numbers = [1, 2, 3]
repeated = numbers * 3  # [1, 2, 3, 1, 2, 3, 1, 2, 3]
檢查元素是否存在
fruits = ["apple", "banana", "cherry"]
print("apple" in fruits)   # True
print("orange" in fruits)  # False

列表方法

添加元素
fruits = ["apple", "banana"]

# append() - 在末尾添加單個元素
fruits.append("cherry")  # ['apple', 'banana', 'cherry']

# extend() - 在末尾添加多個元素
fruits.extend(["date", "elderberry"])  # ['apple', 'banana', 'cherry', 'date', 'elderberry']

# insert() - 在指定位置插入元素
fruits.insert(1, "blueberry")  # ['apple', 'blueberry', 'banana', 'cherry', 'date', 'elderberry']
刪除元素
fruits = ["apple", "banana", "cherry", "banana"]

# remove() - 刪除第一個匹配的元素
fruits.remove("banana")  # ['apple', 'cherry', 'banana']

# pop() - 刪除並返回指定位置的元素
last_fruit = fruits.pop()  # 返回 'banana', fruits變為 ['apple', 'cherry']
second_fruit = fruits.pop(1)  # 返回 'cherry', fruits變為 ['apple']

# clear() - 清空列表
fruits.clear()  # []
查找和計數
fruits = ["apple", "banana", "cherry", "banana"]

# index() - 返回第一個匹配元素的索引
print(fruits.index("banana"))  # 1

# count() - 返回元素出現的次數
print(fruits.count("banana"))  # 2
排序和反轉
numbers = [3, 1, 4, 1, 5, 9, 2]

# sort() - 原地排序
numbers.sort()  # [1, 1, 2, 3, 4, 5, 9]
numbers.sort(reverse=True)  # [9, 5, 4, 3, 2, 1, 1]

# sorted() - 返回新排序列表(不改變原列表)
sorted_numbers = sorted(numbers)  # 原列表不變

# reverse() - 反轉列表
numbers.reverse()  # [1, 1, 2, 3, 4, 5, 9] 變為 [9, 5, 4, 3, 2, 1, 1]
複製列表
original = [1, 2, 3]

# 錯誤的方式(引用同一個對象)
copy_wrong = original  # 修改copy_wrong會影響original

# 正確的方式
# 淺拷貝:原因:淺拷貝只複製了外層列表,而內層列表仍然是引用關係。
copy_correct = original.copy()  # 創建淺拷貝
copy_correct2 = list(original)  # 創建淺拷貝的另一種方式
copy_correct3 = original[:]     # 使用切片創建淺拷貝

# 對於嵌套列表,需要使用深拷貝
import copy
nested_list = [[1, 2], [3, 4]]
deep_copy = copy.deepcopy(nested_list)  # 創建深拷貝

列表推導式

列表推導式:快速創建列表的"魔法公式"

什麼是列表推導式?

簡單説:用一行代碼快速生成一個新列表,代替繁瑣的 for 循環 + append() 操作。

比如,要生成 [1,2,3,4,5] 的平方列表 [1,4,9,16,25]

  • 普通循環寫法:
squares = []
for i in [1,2,3,4,5]:
    squares.append(i * i)
print(squares)  # [1,4,9,16,25]
  • 列表推導式寫法:
squares = [i * i for i in [1,2,3,4,5]]
print(squares)  # [1,4,9,16,25]

核心優勢:簡潔、高效,一眼能看出列表的生成邏輯。

列表推導式的基本結構
[表達式 for 變量 in 可迭代對象]
  • 表達式:對變量的操作(如 i*2str(i) 等),決定新列表的元素
  • 變量:從可迭代對象中依次取出的元素(如 ix 等)
  • 可迭代對象:可以循環的對象(如列表、range、字符串等)
常見用法示例
基礎用法:對可迭代對象的每個元素做處理
# 示例1:生成0-9的偶數列表(每個數×2)
even_numbers = [i * 2 for i in range(10)]
print(even_numbers)  # [0,2,4,6,8,10,12,14,16,18]

# 示例2:將字符串列表中的每個元素轉為大寫
words = ["apple", "banana", "cherry"]
upper_words = [word.upper() for word in words]
print(upper_words)  # ['APPLE', 'BANANA', 'CHERRY']
條件篩選:只保留符合條件的元素

結構:[表達式 for 變量 in 可迭代對象 if 條件]

# 示例1:篩選出1-10中的奇數
odd_numbers = [i for i in range(1, 11) if i % 2 == 1]
print(odd_numbers)  # [1,3,5,7,9]

# 示例2:篩選出列表中長度大於3的字符串
words = ["a", "bb", "ccc", "dddd", "eeeee"]
long_words = [word for word in words if len(word) > 3]
print(long_words)  # ['dddd', 'eeeee']
複雜表達式:多步操作或嵌套邏輯
# 示例1:計算1-5中每個數的平方,再篩選出大於10的結果
filtered_squares = [i*i for i in range(1,6) if i*i > 10]
print(filtered_squares)  # [16,25](4²=16,5²=25)

# 示例2:嵌套循環(flatten 二維列表)
matrix = [[1,2], [3,4], [5,6]]
flat_list = [num for row in matrix for num in row]
print(flat_list)  # [1,2,3,4,5,6](相當於兩層for循環)
為什麼要用列表推導式?
  1. 代碼更短:一行解決循環 + append 的工作,減少冗餘
  2. 可讀性高:邏輯集中,容易理解生成列表的規則
  3. 效率更高:比普通 for 循環執行速度更快(底層優化

列表與函數

常用函數
fruits = ["apple", "banana", "cherry"]

# len() - 獲取列表長度
print(len(fruits))  # 3

# min() 和 max() - 查找最小和最大值
numbers = [3, 1, 4, 1, 5, 9, 2]
print(min(numbers))  # 1
print(max(numbers))  # 9

# sum() - 求和
numbers = [1, 2, 3, 4, 5]
print(sum(numbers))  # 15

# any() 和 all() - 檢查條件
bools = [True, False, True]
print(any(bools))  # True (至少有一個為True)
print(all(bools))  # False (不全為True)

元組(Tuple)

什麼是元組?

元組(Tuple)是 Python 中的一種不可變序列數據類型,用於存儲多個有序元素。

元組的特點

  • 不可變性:一旦創建,不能修改、添加或刪除元素
  • 有序性:元素按定義順序存儲,可通過索引訪問
  • 可重複性:元素可以重複
  • 可哈希性:可作為字典的鍵(因為不可變)

創建元組

基本創建方法
# 空元組
empty_tuple = ()

# 單元素元組(注意逗號)
single_tuple = (42,)

# 多元素元組
numbers = (1, 2, 3, 4, 5)

# 混合類型元組
mixed = ("apple", 3.14, True, [1, 2, 3])
其他創建方式
# 使用tuple()構造函數
tuple_from_list = tuple([1, 2, 3])
  # (1, 2, 3)tuple_from_string = tuple("hello")  # ('h', 'e', 'l', 'l', 'o')
# 省略圓括號
implicit_tuple = 1, 2, 3  # (1, 2, 3)
single_implicit = 42,     # (42,)

元組的基本操作

訪問元素
fruits = ("apple", "banana", "cherry", "date", "elderberry")

# 索引訪問
print(fruits[0])    # "apple" - 正向索引
print(fruits[-1])   # "elderberry" - 負向索引

# 切片操作
print(fruits[1:3])  # ("banana", "cherry")
print(fruits[:2])   # ("apple", "banana")
print(fruits[3:])   # ("date", "elderberry")
元組運算
tuple1 = (1, 2, 3)
tuple2 = (4, 5, 6)

# 連接運算
combined = tuple1 + tuple2  # (1, 2, 3, 4, 5, 6)

# 重複運算
repeated = tuple1 * 3  # (1, 2, 3, 1, 2, 3, 1, 2, 3)

# 成員檢測
print(2 in tuple1)      # True
print(7 not in tuple1)  # True

# 長度計算
print(len(tuple1))      # 3
元組方法
numbers = (1, 2, 2, 3, 4, 2, 5)

# count() - 統計元素出現次數
print(numbers.count(2))  # 3

# index() - 查找元素第一次出現的索引
print(numbers.index(3))  # 3

元組解包

基本解包
# 簡單解包
person = ("Alice", 25, "Engineer")
name, age, job = person
print(f"{name} is {age} years old and works as a {job}")

# 交換變量值
a, b = 10, 20
a, b = b, a  # 交換a和b的值
print(a, b)  # 20 10
星號解包
# 使用*收集剩餘元素
first, *middle, last = (1, 2, 3, 4, 5)
print(first)   # 1
print(middle)  # [2, 3, 4] (注意:middle是列表)
print(last)    # 5

# 忽略某些元素
name, _, age = ("Bob", "ignore_this", 30)
print(name, age)  # Bob 30

元組的實際應用

函數返回多個值
def calculate_stats(numbers):
    """計算數字列表的最小值、最大值和平均值"""
    return min(numbers), max(numbers), sum(numbers) / len(numbers)

# 使用元組解包接收多個返回值
data = [10, 20, 30, 40, 50]
min_val, max_val, avg_val = calculate_stats(data)
print(f"最小值: {min_val}, 最大值: {max_val}, 平均值: {avg_val:.2f}")
保護數據不被修改
# 配置信息(不希望被修改)
DATABASE_CONFIG = ("localhost", 3306, "my_database", "user", "password")

# 座標系統(作為字典鍵)
points = {
    (0, 0): "原點",
    (1, 2): "點A", 
    (3, 4): "點B"
}

def get_point_name(x, y):
    return points.get((x, y), "未知點")

print(get_point_name(1, 2))  # 點A

元組與列表的轉換

# 列表轉元組
fruits_list = ["apple", "banana", "cherry"]
fruits_tuple = tuple(fruits_list)
print(fruits_tuple)  # ('apple', 'banana', 'cherry')

# 元組轉列表
numbers_tuple = (1, 2, 3, 4, 5)
numbers_list = list(numbers_tuple)
print(numbers_list)  # [1, 2, 3, 4, 5]

# 修改後轉回元組(間接修改元組的方法)
numbers_list.append(6)
numbers_tuple = tuple(numbers_list)
print(numbers_tuple)  # (1, 2, 3, 4, 5, 6)

集合(Set)

集合是 Python 中的一種內置數據類型,用於存儲無序、不重複的元素。集合非常適合用於成員檢測、消除重複元素以及數學集合運算。

創建集合

使用花括號
# 創建集合
fruits = {"apple", "banana", "cherry"}
print(fruits)  # 輸出: {'banana', 'apple', 'cherry'}(順序可能不同)
使用set()構造函數
# 從列表創建集合
numbers = set([1, 2, 3, 4, 5])
print(numbers)  # 輸出: {1, 2, 3, 4, 5}

# 從元組創建集合
colors = set(("red", "green", "blue"))
print(colors)  # 輸出: {'red', 'green', 'blue'}

# 從字符串創建集合(每個字符成為單獨元素)
chars = set("hello")
print(chars)  # 輸出: {'h', 'e', 'l', 'o'}

集合的基本操作

添加元素
fruits = {"apple", "banana"}
fruits.add("orange")
print(fruits)  # 輸出: {'banana', 'orange', 'apple'}

# 添加多個元素
fruits.update(["mango", "grape"])
print(fruits)  # 輸出: {'banana', 'mango', 'apple', 'grape', 'orange'}
刪除元素
fruits = {"apple", "banana", "cherry"}

# remove() - 如果元素不存在會報錯
fruits.remove("banana")
print(fruits)  # 輸出: {'apple', 'cherry'}

# discard() - 如果元素不存在不會報錯
fruits.discard("mango")  # 不會報錯

# pop() - 隨機刪除一個元素
removed_item = fruits.pop()
print(f"刪除了: {removed_item}")  # 輸出隨機一個元素

# clear() - 清空集合
fruits.clear()
print(fruits)  # 輸出: set()
檢查元素是否存在
fruits = {"apple", "banana", "cherry"}
print("apple" in fruits)  # 輸出: True
print("mango" not in fruits)  # 輸出: True

集合運算

並集 (Union)
set1 = {1, 2, 3}
set2 = {3, 4, 5}

# 方法1: 使用 | 運算符
union_set = set1 | set2
print(union_set)  # 輸出: {1, 2, 3, 4, 5}

# 方法2: 使用 union() 方法
union_set = set1.union(set2)
print(union_set)  # 輸出: {1, 2, 3, 4, 5}
交集 (Intersection)
set1 = {1, 2, 3}
set2 = {3, 4, 5}

# 方法1: 使用 & 運算符
intersection_set = set1 & set2
print(intersection_set)  # 輸出: {3}

# 方法2: 使用 intersection() 方法
intersection_set = set1.intersection(set2)
print(intersection_set)  # 輸出: {3}
差集 (Difference)
set1 = {1, 2, 3}
set2 = {3, 4, 5}

# 方法1: 使用 - 運算符
difference_set = set1 - set2
print(difference_set)  # 輸出: {1, 2}

# 方法2: 使用 difference() 方法
difference_set = set1.difference(set2)
print(difference_set)  # 輸出: {1, 2}
對稱差集 (Symmetric Difference)
set1 = {1, 2, 3}
set2 = {3, 4, 5}

# 方法1: 使用 ^ 運算符
symmetric_difference_set = set1 ^ set2
print(symmetric_difference_set)  # 輸出: {1, 2, 4, 5}

# 方法2: 使用 symmetric_difference() 方法
symmetric_difference_set = set1.symmetric_difference(set2)
print(symmetric_difference_set)  # 輸出: {1, 2, 4, 5}

集合比較

set1 = {1, 2, 3}
set2 = {1, 2}
set3 = {1, 2, 3, 4}

# 子集檢查
print(set2.issubset(set1))  # 輸出: True
print(set2 <= set1)        # 輸出: True

# 真子集檢查
print(set2 < set1)         # 輸出: True
print(set1 < set1)         # 輸出: False

# 超集檢查
print(set1.issuperset(set2))  # 輸出: True
print(set1 >= set2)           # 輸出: True

# 真超集檢查
print(set1 > set2)        # 輸出: True
print(set1 > set1)        # 輸出: False

# 不相交檢查
set4 = {4, 5}
print(set1.isdisjoint(set4))  # 輸出: True

集合推導式

# 創建一個包含平方數的集合
squares = {x**2 for x in range(10)}
print(squares)  # 輸出: {0, 1, 4, 9, 16, 25, 36, 49, 64, 81}

# 創建一個只包含偶數的平方數的集合
even_squares = {x**2 for x in range(10) if x % 2 == 0}
print(even_squares)  # 輸出: {0, 4, 16, 36, 64}

不可變集合 (Frozen Set)

# 創建不可變集合
frozen_set = frozenset([1, 2, 3, 4, 5])
print(frozen_set)  # 輸出: frozenset({1, 2, 3, 4, 5})

# 不可變集合不能添加或刪除元素
# frozen_set.add(6)  # 這會報錯: AttributeError

# 但可以進行集合運算
other_set = frozenset([4, 5, 6, 7])
print(frozen_set & other_set)  # 輸出: frozenset({4, 5})

字典(Dictionary)

字典是 Python 中一種非常重要的數據結構,它存儲鍵值對(key-value pairs)。字典中的鍵必須是不可變類型(如字符串、數字、元組等),且鍵是唯一的。值可以是任意類型。

創建字典

使用花括號
# 創建字典
person = {"name": "Alice", "age": 25, "city": "New York"}
print(person)  # 輸出: {'name': 'Alice', 'age': 25, 'city': 'New York'}
使用dict()構造函數
# 使用鍵值對參數
person = dict(name="Bob", age=30, city="Boston")
print(person)  # 輸出: {'name': 'Bob', 'age': 30, 'city': 'Boston'}

# 使用元組列表
person = dict([("name", "Charlie"), ("age", 35), ("city", "Chicago")])
print(person)  # 輸出: {'name': 'Charlie', 'age': 35, 'city': 'Chicago'}
使用字典推導式
# 創建一個鍵為數字,值為其平方的字典
squares = {x: x**2 for x in range(1, 6)}
print(squares)  # 輸出: {1: 1, 2: 4, 3: 9, 4: 16, 5: 25}

訪問字典元素

通過鍵訪問值
person = {"name": "Alice", "age": 25}
print(person["name"])  # 輸出: Alice
# print(person["gender"])  # 如果鍵不存在,會報KeyError
使用get()方法避免KeyError
print(person.get("age"))    # 輸出: 25
print(person.get("gender")) # 輸出: None(不會報錯)
print(person.get("gender", "Not specified"))  # 輸出: Not specified(默認值)

修改字典

添加或更新鍵值對
person = {"name": "Alice", "age": 25}
person["age"] = 26  # 更新已有鍵的值
person["city"] = "New York"  # 添加新鍵值對
print(person)  # 輸出: {'name': 'Alice', 'age': 26, 'city': 'New York'}
使用update()方法合併字典
person = {"name": "Alice", "age": 25}
extra_info = {"city": "New York", "gender": "Female"}
person.update(extra_info)
print(person)  # 輸出: {'name': 'Alice', 'age': 25, 'city': 'New York', 'gender': 'Female'}

刪除元素

使用del語句
person = {"name": "Alice", "age": 25, "city": "New York"}
del person["age"]
print(person)  # 輸出: {'name': 'Alice', 'city': 'New York'}
使用pop()方法
person = {"name": "Alice", "age": 25, "city": "New York"}
age = person.pop("age")
print(age)     # 輸出: 25
print(person)  # 輸出: {'name': 'Alice', 'city': 'New York'}

# 如果鍵不存在,可以提供默認值以避免錯誤
gender = person.pop("gender", "Not specified")
print(gender)  # 輸出: Not specified
使用clear()清空字典
person.clear()
print(person)  # 輸出: {}

字典的常用方法

獲取所有鍵、值和鍵值對
person = {"name": "Alice", "age": 25, "city": "New York"}

keys = person.keys()
print(keys)