什麼是容器?
為什麼需要容器?
想象一下:如果你只有一個蘋果,直接拿在手裏就行;但如果你有一堆蘋果,就需要一個袋子或籃子來裝它們。
Python 中的數據也是如此:
- 當你只有一個數字(比如
3)、一個字符串(比如"hello")時,直接用變量存就行 - 但當你有一組相關的數據(比如全班同學的名字、一個月的氣温數據)時,就需要用"容器"來統一管理這些數據,方便操作(比如遍歷、查找、添加等)
什麼是容器?
簡單説,能同時裝多個數據的東西,就是容器。
Python 中最常見的容器有:
- 列表(list):用
[]表示,比如[1, 2, 3],像個有序的"抽屜",可以隨時添加/刪除東西 - 元組(tuple):用
()表示,比如(1, 2, 3),像個封死的"盒子",裏面的東西不能改 - 字典(dict):用
{}表示,比如{"name": "小明", "age": 18},像個帶標籤的"儲物櫃",每個東西都有自己的名字(鍵) - 集合(set):用
{}表示,比如{1, 2, 3},像個無序的"筐",裏面不能有重複的東西
1. 字符串內存模型
變量是最不穩定的,存儲在棧中。
局部變量的引用關係通常存儲在棧中,而變量的不穩定性(生命週期短、隨函數調用動態創建銷燬)與棧內存的特性高度匹配。
字符串用的最多,存儲在常量區。
結論:字符串數據不能更改,是不可變數據
2. 整數內存模型
對於小於-5或大於256的整數,Python 不會預先緩存,而是在每次創建時動態分配內存(存儲在堆區)。即使兩個大整數的值相同,它們也會被視為不同的對象,佔用不同的內存地址。
小整數(-5 到 256)
- 這些整數被緩存並在整個程序中重複使用
- 它們存儲在特殊的小整數池中,而不是堆內存中
常規整數
- 對於大多數系統,常規整數是32位或64位
- 這些整數直接存儲在對象的內存空間中(通常在棧上)
大整數(超出系統字長)
- 當整數太大無法放入單個機器字時,Python 會在堆內存中分配空間
- 這些整數使用可變長度的數據結構存儲
- 每個大整數對象包含:
- 引用計數
- 類型信息
- 實際數值數據(以數組形式存儲)
列表(List)
什麼是列表?
列表(List)是 Python 中最基本、最常用的數據結構之一。它是一個有序、可變的元素集合,可以包含任何類型的對象,甚至可以是混合類型。
列表的基本特性
- 有序性:列表中的元素按特定順序排列
- 可變性:可以修改列表的內容(增刪改)
- 異構性:可以包含不同類型的元素
- 可嵌套:列表中可以包含其他列表(嵌套列表)
- 可迭代:可以使用循環遍歷列表中的元素
創建列表
使用方括號創建
# 空列表
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*2、str(i)等),決定新列表的元素 - 變量:從可迭代對象中依次取出的元素(如
i、x等) - 可迭代對象:可以循環的對象(如列表、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循環)
為什麼要用列表推導式?
- 代碼更短:一行解決循環 + append 的工作,減少冗餘
- 可讀性高:邏輯集中,容易理解生成列表的規則
- 效率更高:比普通 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)