Python 数据类型
目录
概述
Python是一种动态类型语言,变量不需要声明类型,解释器会根据赋值自动推断数据类型。Python提供了丰富的内置数据类型,每种类型都有其特定的用途和操作方法。
数据类型分类
# 基本数据类型
- 数值类型: int, float, complex
- 字符串类型: str
- 布尔类型: bool
- 空值类型: NoneType
# 容器数据类型
- 序列类型: list, tuple, str
- 映射类型: dict
- 集合类型: set, frozenset
查看数据类型
# 使用type()函数查看变量的类型
x = 10
print(type(x)) # <class 'int'>
name = "Alice"
print(type(name)) # <class 'str'>
# 使用isinstance()检查类型
print(isinstance(x, int)) # True
print(isinstance(name, str)) # True
print(isinstance(x, (int, float))) # True (检查多个类型)
数值类型
1. 整数(int)
整数是没有小数部分的数字,可以是正数、负数或零。
# 整数定义
age = 25
temperature = -10
zero = 0
big_number = 1000000
# 不同进制表示
decimal = 100 # 十进制
binary = 0b1100100 # 二进制 (等于100)
octal = 0o144 # 八进制 (等于100)
hexadecimal = 0x64 # 十六进制 (等于100)
print(decimal) # 100
print(binary) # 100
print(octal) # 100
print(hexadecimal) # 100
# 大整数(Python支持任意精度)
huge_number = 10 ** 100
print(huge_number)
print(type(huge_number)) # <class 'int'>
整数运算
a = 10
b = 3
# 基本运算
print(a + b) # 加法: 13
print(a - b) # 减法: 7
print(a * b) # 乘法: 30
print(a / b) # 除法: 3.333... (结果是float)
print(a // b) # 整除: 3
print(a % b) # 取模: 1
print(a ** b) # 幂运算: 1000
# 位运算
print(a & b) # 按位与: 2
print(a | b) # 按位或: 11
print(a ^ b) # 按位异或: 9
print(~a) # 按位取反: -11
print(a << 1) # 左移: 20
print(a >> 1) # 右移: 5
2. 浮点数(float)
浮点数是带有小数部分的数字,用于表示实数。
# 浮点数定义
price = 99.99
pi = 3.14159
temperature = -5.5
scientific = 1.23e4 # 科学计数法: 12300.0
small = 1.23e-4 # 科学计数法: 0.000123
print(price) # 99.99
print(scientific) # 12300.0
print(type(price)) # <class 'float'>
浮点数精度问题
# 浮点数精度问题
print(0.1 + 0.2) # 0.30000000000000004 (不是精确的0.3)
print(0.1 + 0.2 == 0.3) # False
# 解决方案1: 使用round()
result = round(0.1 + 0.2, 10)
print(result == 0.3) # True
# 解决方案2: 使用decimal模块(高精度计算)
from decimal import Decimal
print(Decimal('0.1') + Decimal('0.2')) # 0.3
浮点数运算
import math
x = 10.5
y = 3.2
# 基本运算
print(x + y) # 13.7
print(x - y) # 7.3
print(x * y) # 33.6
print(x / y) # 3.28125
print(x // y) # 3.0 (整除)
print(x % y) # 0.9 (取模)
print(x ** y) # 幂运算
# 数学函数
print(abs(-10.5)) # 绝对值: 10.5
print(round(3.14159, 2)) # 四舍五入: 3.14
print(math.floor(3.7)) # 向下取整: 3
print(math.ceil(3.2)) # 向上取整: 4
print(math.sqrt(16)) # 平方根: 4.0
print(math.pow(2, 3)) # 幂: 8.0
3. 复数(complex)
复数由实部和虚部组成,形式为 a + bj。
# 复数定义
z1 = 3 + 4j
z2 = complex(3, 4) # 另一种定义方式
print(z1) # (3+4j)
print(z1.real) # 实部: 3.0
print(z1.imag) # 虚部: 4.0
print(type(z1)) # <class 'complex'>
# 复数运算
z3 = z1 + z2
print(z3) # (6+8j)
z4 = z1 * z2
print(z4) # (-7+24j)
# 共轭复数
print(z1.conjugate()) # (3-4j)
# 模(绝对值)
print(abs(z1)) # 5.0
字符串类型
字符串是字符的序列,用于表示文本数据。
字符串定义
# 单引号
name = 'Alice'
# 双引号
greeting = "Hello, World!"
# 三引号(多行字符串)
multi_line = """这是
一个
多行字符串"""
# 转义字符
text = "He said, \"Hello!\""
newline = "Line 1\nLine 2"
tab = "Column1\tColumn2"
backslash = "Path: C:\\Users\\Name"
print(text) # He said, "Hello!"
print(newline) # Line 1
# Line 2
原始字符串
# 原始字符串(不处理转义字符)
path = r"C:\Users\Name\Documents"
regex = r"\d+\.\d+" # 正则表达式常用
print(path) # C:\Users\Name\Documents
字符串操作
text = "Hello, World!"
# 长度
print(len(text)) # 13
# 索引访问
print(text[0]) # H
print(text[-1]) # !
print(text[7]) # W
# 切片
print(text[0:5]) # Hello
print(text[7:]) # World!
print(text[:5]) # Hello
print(text[::2]) # Hlo ol!
# 拼接
first = "Hello"
last = "World"
full = first + ", " + last + "!"
print(full) # Hello, World!
# 重复
repeat = "Ha" * 3
print(repeat) # HaHaHa
字符串方法
text = " Hello, World! "
# 大小写转换
print(text.upper()) # " HELLO, WORLD! "
print(text.lower()) # " hello, world! "
print(text.title()) # " Hello, World! "
print(text.capitalize()) # " hello, world! "
print(text.swapcase()) # " hELLO, wORLD! "
# 去除空白
print(text.strip()) # "Hello, World!"
print(text.lstrip()) # "Hello, World! "
print(text.rstrip()) # " Hello, World!"
# 查找和替换
text2 = "Hello, World!"
print(text2.find("World")) # 7 (找到返回索引)
print(text2.find("Python")) # -1 (未找到)
print(text2.replace("World", "Python")) # "Hello, Python!"
print(text2.count("l")) # 3
# 判断
print("hello".isalpha()) # True (全是字母)
print("123".isdigit()) # True (全是数字)
print("hello123".isalnum()) # True (字母或数字)
print(" ".isspace()) # True (全是空白)
print("Hello".startswith("He")) # True
print("Hello".endswith("lo")) # True
# 分割和连接
csv = "apple,banana,orange"
fruits = csv.split(",")
print(fruits) # ['apple', 'banana', 'orange']
joined = "-".join(fruits)
print(joined) # apple-banana-orange
# 填充和对齐
print("42".zfill(5)) # 00042
print("Hello".center(20)) # " Hello "
print("Hello".ljust(20)) # "Hello "
print("Hello".rjust(20)) # " Hello"
字符串格式化
name = "Alice"
age = 25
score = 95.5
# f-string (推荐,Python 3.6+)
message = f"My name is {name}, I'm {age} years old."
print(message)
# 表达式
print(f"Next year I'll be {age + 1}")
print(f"Score: {score:.2f}") # 保留两位小数: 95.50
# format()方法
message = "My name is {}, I'm {} years old.".format(name, age)
print(message)
message = "My name is {0}, I'm {1} years old.".format(name, age)
print(message)
message = "My name is {name}, I'm {age} years old.".format(name=name, age=age)
print(message)
# %格式化(旧式)
message = "My name is %s, I'm %d years old." % (name, age)
print(message)
布尔类型
布尔类型只有两个值:True和False,用于逻辑判断。
# 布尔值
is_active = True
is_deleted = False
print(type(is_active)) # <class 'bool'>
# 布尔实际上是int的子类
print(True == 1) # True
print(False == 0) # True
print(True + 1) # 2
print(False + 1) # 1
布尔运算
# 逻辑运算
print(True and False) # False (与)
print(True or False) # True (或)
print(not True) # False (非)
# 短路求值
result = False and print("不会执行") # 不会打印
result = True or print("不会执行") # 不会打印
比较运算
# 比较运算符返回布尔值
print(10 > 5) # True
print(10 < 5) # False
print(10 >= 10) # True
print(10 <= 5) # False
print(10 == 10) # True
print(10 != 5) # True
# 链式比较
x = 10
print(5 < x < 15) # True (等价于 5 < x and x < 15)
print(5 < x < 8) # False
真值测试
# 以下值被视为False
print(bool(False)) # False
print(bool(None)) # False
print(bool(0)) # False
print(bool(0.0)) # False
print(bool("")) # False (空字符串)
print(bool([])) # False (空列表)
print(bool(())) # False (空元组)
print(bool({})) # False (空字典)
print(bool(set())) # False (空集合)
# 其他值都被视为True
print(bool(1)) # True
print(bool(-1)) # True
print(bool("hello")) # True
print(bool([1, 2])) # True
列表类型
列表是有序的、可变的序列,可以存储不同类型的元素。
列表创建
# 创建列表
fruits = ["apple", "banana", "orange"]
numbers = [1, 2, 3, 4, 5]
mixed = [1, "hello", 3.14, True, None]
empty = []
nested = [[1, 2], [3, 4], [5, 6]]
# 使用list()构造函数
chars = list("hello")
print(chars) # ['h', 'e', 'l', 'l', 'o']
range_list = list(range(5))
print(range_list) # [0, 1, 2, 3, 4]
列表访问
fruits = ["apple", "banana", "orange", "grape", "kiwi"]
# 索引访问
print(fruits[0]) # apple
print(fruits[2]) # orange
print(fruits[-1]) # kiwi (最后一个)
print(fruits[-2]) # grape (倒数第二个)
# 切片
print(fruits[1:3]) # ['banana', 'orange']
print(fruits[:3]) # ['apple', 'banana', 'orange']
print(fruits[2:]) # ['orange', 'grape', 'kiwi']
print(fruits[::2]) # ['apple', 'orange', 'kiwi']
print(fruits[::-1]) # ['kiwi', 'grape', 'orange', 'banana', 'apple'] (反转)
列表修改
fruits = ["apple", "banana", "orange"]
# 修改元素
fruits[1] = "grape"
print(fruits) # ['apple', 'grape', 'orange']
# 添加元素
fruits.append("kiwi") # 添加到末尾
print(fruits) # ['apple', 'grape', 'orange', 'kiwi']
fruits.insert(1, "mango") # 插入到指定位置
print(fruits) # ['apple', 'mango', 'grape', 'orange', 'kiwi']
fruits.extend(["pear", "peach"]) # 扩展列表
print(fruits) # ['apple', 'mango', 'grape', 'orange', 'kiwi', 'pear', 'peach']
# 删除元素
fruits.remove("grape") # 删除指定值(第一个匹配)
print(fruits)
deleted = fruits.pop() # 删除并返回最后一个元素
print(deleted) # peach
print(fruits)
deleted = fruits.pop(1) # 删除并返回指定索引的元素
print(deleted) # mango
print(fruits)
del fruits[0] # 删除指定索引
print(fruits)
fruits.clear() # 清空列表
print(fruits) # []
列表操作
numbers = [3, 1, 4, 1, 5, 9, 2, 6]
# 长度
print(len(numbers)) # 8
# 最大值/最小值
print(max(numbers)) # 9
print(min(numbers)) # 1
# 求和
print(sum(numbers)) # 31
# 排序
numbers.sort() # 原地排序
print(numbers) # [1, 1, 2, 3, 4, 5, 6, 9]
numbers.sort(reverse=True) # 降序
print(numbers) # [9, 6, 5, 4, 3, 2, 1, 1]
sorted_numbers = sorted(numbers) # 返回新列表
print(sorted_numbers)
# 反转
numbers.reverse()
print(numbers) # [1, 1, 2, 3, 4, 5, 6, 9]
# 计数
print(numbers.count(1)) # 2
# 查找索引
print(numbers.index(4)) # 4
列表推导式
# 基本列表推导式
squares = [x**2 for x in range(10)]
print(squares) # [0, 1, 4, 9, 16, 25, 36, 49, 64, 81]
# 带条件的列表推导式
evens = [x for x in range(20) if x % 2 == 0]
print(evens) # [0, 2, 4, 6, 8, 10, 12, 14, 16, 18]
# 嵌套列表推导式
matrix = [[i*j for j in range(3)] for i in range(3)]
print(matrix) # [[0, 0, 0], [0, 1, 2], [0, 2, 4]]
# 字符串处理
words = ["hello", "world", "python"]
upper_words = [word.upper() for word in words]
print(upper_words) # ['HELLO', 'WORLD', 'PYTHON']
列表复制
# 浅拷贝
original = [1, 2, [3, 4]]
copy1 = original.copy()
copy2 = original[:]
copy3 = list(original)
# 修改副本不影响原列表(对于不可变元素)
copy1.append(5)
print(original) # [1, 2, [3, 4]]
print(copy1) # [1, 2, [3, 4], 5]
# 但对于嵌套的可变对象,浅拷贝会共享引用
copy1[2].append(5)
print(original) # [1, 2, [3, 4, 5]] (被影响了!)
# 深拷贝
import copy
original = [1, 2, [3, 4]]
deep_copy = copy.deepcopy(original)
deep_copy[2].append(5)
print(original) # [1, 2, [3, 4]] (不受影响)
print(deep_copy) # [1, 2, [3, 4, 5]]
元组类型
元组是有序的、不可变的序列。
元组创建
# 创建元组
coordinates = (10, 20)
colors = ("red", "green", "blue")
single = (42,) # 单元素元组需要逗号
empty = ()
# 不使用括号(元组打包)
point = 10, 20, 30
print(point) # (10, 20, 30)
print(type(point)) # <class 'tuple'>
# 使用tuple()构造函数
tuple_from_list = tuple([1, 2, 3])
print(tuple_from_list) # (1, 2, 3)
tuple_from_string = tuple("hello")
print(tuple_from_string) # ('h', 'e', 'l', 'l', 'o')
元组访问
coordinates = (10, 20, 30)
# 索引访问
print(coordinates[0]) # 10
print(coordinates[-1]) # 30
# 切片
print(coordinates[1:]) # (20, 30)
# 元组不可修改
# coordinates[0] = 100 # ❌ TypeError
元组解包
# 基本解包
point = (10, 20, 30)
x, y, z = point
print(x, y, z) # 10 20 30
# 交换变量
a = 10
b = 20
a, b = b, a
print(a, b) # 20 10
# 使用*收集多余元素
numbers = (1, 2, 3, 4, 5)
first, *middle, last = numbers
print(first) # 1
print(middle) # [2, 3, 4]
print(last) # 5
# 函数返回多个值
def get_user():
return "Alice", 25, "alice@example.com"
name, age, email = get_user()
print(name, age, email)
元组方法
numbers = (1, 2, 3, 2, 4, 2, 5)
# 计数
print(numbers.count(2)) # 3
# 查找索引
print(numbers.index(3)) # 2
元组的用途
# 1. 作为字典的键(因为不可变)
locations = {
(40.7128, -74.0060): "New York",
(51.5074, -0.1278): "London"
}
# 2. 函数返回多个值
def divide(a, b):
quotient = a // b
remainder = a % b
return quotient, remainder
q, r = divide(10, 3)
print(q, r) # 3 1
# 3. 保护数据不被修改
CONSTANTS = (3.14159, 2.71828, 1.41421)
字典类型
字典是无序的(Python 3.7+保持插入顺序)键值对集合。
字典创建
# 创建字典
user = {
"name": "Alice",
"age": 25,
"email": "alice@example.com"
}
# 使用dict()构造函数
user2 = dict(name="Bob", age=30, email="bob@example.com")
# 从键值对列表创建
pairs = [("name", "Charlie"), ("age", 35)]
user3 = dict(pairs)
# 空字典
empty = {}
empty2 = dict()
字典访问
user = {"name": "Alice", "age": 25, "email": "alice@example.com"}
# 通过键访问
print(user["name"]) # Alice
print(user["age"]) # 25
# 使用get()方法(更安全)
print(user.get("name")) # Alice
print(user.get("phone")) # None (键不存在)
print(user.get("phone", "N/A")) # N/A (提供默认值)
# 获取所有键、值、键值对
print(user.keys()) # dict_keys(['name', 'age', 'email'])
print(user.values()) # dict_values(['Alice', 25, 'alice@example.com'])
print(user.items()) # dict_items([('name', 'Alice'), ('age', 25), ...])
字典修改
user = {"name": "Alice", "age": 25}
# 添加/更新键值对
user["email"] = "alice@example.com" # 添加
user["age"] = 26 # 更新
print(user)
# 使用update()方法
user.update({"phone": "123456", "city": "Beijing"})
print(user)
# 删除
del user["phone"] # 删除指定键
email = user.pop("email") # 删除并返回值
print(email) # alice@example.com
key, value = user.popitem() # 删除并返回最后一个键值对
print(key, value)
user.clear() # 清空字典
print(user) # {}
字典遍历
user = {"name": "Alice", "age": 25, "email": "alice@example.com"}
# 遍历键
for key in user:
print(key)
# 遍历值
for value in user.values():
print(value)
# 遍历键值对
for key, value in user.items():
print(f"{key}: {value}")
# 字典推导式
squares = {x: x**2 for x in range(5)}
print(squares) # {0: 0, 1: 1, 2: 4, 3: 9, 4: 16}
# 带条件的字典推导式
even_squares = {x: x**2 for x in range(10) if x % 2 == 0}
print(even_squares) # {0: 0, 2: 4, 4: 16, 6: 36, 8: 64}
字典方法
user = {"name": "Alice", "age": 25}
# 检查键是否存在
print("name" in user) # True
print("phone" in user) # False
# 设置默认值
user.setdefault("phone", "N/A")
print(user) # {'name': 'Alice', 'age': 25, 'phone': 'N/A'}
# 合并字典(Python 3.9+)
dict1 = {"a": 1, "b": 2}
dict2 = {"c": 3, "d": 4}
merged = dict1 | dict2
print(merged) # {'a': 1, 'b': 2, 'c': 3, 'd': 4}
# 或使用update()
dict1.update(dict2)
print(dict1) # {'a': 1, 'b': 2, 'c': 3, 'd': 4}
嵌套字典
# 嵌套字典
students = {
"student1": {
"name": "Alice",
"age": 20,
"grades": {"math": 90, "english": 85}
},
"student2": {
"name": "Bob",
"age": 22,
"grades": {"math": 78, "english": 92}
}
}
# 访问嵌套值
print(students["student1"]["name"]) # Alice
print(students["student1"]["grades"]["math"]) # 90
# 修改嵌套值
students["student1"]["grades"]["math"] = 95
集合类型
集合是无序的、不重复元素的集合。
集合创建
# 创建集合
fruits = {"apple", "banana", "orange"}
numbers = {1, 2, 3, 4, 5}
# 使用set()构造函数
fruits2 = set(["apple", "banana", "orange"])
empty_set = set() # 注意: {}是空字典,不是空集合
# 从字符串创建
chars = set("hello")
print(chars) # {'h', 'e', 'l', 'o'} (自动去重)
集合操作
fruits = {"apple", "banana", "orange"}
# 添加元素
fruits.add("grape")
print(fruits)
# 添加多个元素
fruits.update(["kiwi", "mango"])
print(fruits)
# 删除元素
fruits.remove("banana") # 如果元素不存在,抛出KeyError
fruits.discard("pear") # 如果元素不存在,不报错
deleted = fruits.pop() # 随机删除并返回一个元素
print(deleted)
fruits.clear() # 清空集合
集合运算
set1 = {1, 2, 3, 4, 5}
set2 = {4, 5, 6, 7, 8}
# 并集
print(set1 | set2) # {1, 2, 3, 4, 5, 6, 7, 8}
print(set1.union(set2)) # {1, 2, 3, 4, 5, 6, 7, 8}
# 交集
print(set1 & set2) # {4, 5}
print(set1.intersection(set2)) # {4, 5}
# 差集
print(set1 - set2) # {1, 2, 3}
print(set1.difference(set2)) # {1, 2, 3}
# 对称差集(只在一个集合中的元素)
print(set1 ^ set2) # {1, 2, 3, 6, 7, 8}
print(set1.symmetric_difference(set2)) # {1, 2, 3, 6, 7, 8}
# 子集和超集
set3 = {1, 2}
print(set3.issubset(set1)) # True
print(set1.issuperset(set3)) # 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}
集合应用
# 1. 去重
numbers = [1, 2, 2, 3, 3, 3, 4, 4, 4, 4]
unique = list(set(numbers))
print(unique) # [1, 2, 3, 4]
# 2. 查找共同元素
list1 = [1, 2, 3, 4, 5]
list2 = [4, 5, 6, 7, 8]
common = set(list1) & set(list2)
print(common) # {4, 5}
# 3. 成员测试(比列表快)
fruits_set = {"apple", "banana", "orange"}
print("apple" in fruits_set) # True (O(1)时间复杂度)
None类型
None表示空值或无值,是NoneType类型的唯一值。
# None的定义
result = None
print(result) # None
print(type(result)) # <class 'NoneType'>
# None是单例
print(None is None) # True
# 函数没有返回值时返回None
def say_hello():
print("Hello")
result = say_hello()
print(result) # None
# 检查None
value = None
if value is None:
print("值为空")
# 不要使用 == 比较None
# if value == None: # 不推荐
# pass
None的常见用途
# 1. 默认参数
def greet(name=None):
if name is None:
name = "Guest"
return f"Hello, {name}"
print(greet()) # Hello, Guest
print(greet("Alice")) # Hello, Alice
# 2. 初始化变量
result = None
# ... 一些计算 ...
if result is None:
print("计算未完成")
# 3. 表示可选值
user = {
"name": "Alice",
"age": 25,
"phone": None # 电话号码未知
}
类型检查与转换
类型检查
# type()函数
x = 10
print(type(x)) # <class 'int'>
print(type(x) == int) # True
# isinstance()函数(推荐)
print(isinstance(x, int)) # True
print(isinstance(x, (int, float))) # True (检查多个类型)
# 类型提示
def add(a: int, b: int) -> int:
return a + b
age: int = 25
name: str = "Alice"
scores: list[float] = [90.5, 85.0, 92.5]
类型转换
# 转换为整数
print(int(3.7)) # 3 (截断小数部分)
print(int("10")) # 10
print(int(True)) # 1
print(int(False)) # 0
# print(int("3.5")) # ❌ ValueError
# 转换为浮点数
print(float(10)) # 10.0
print(float("3.14")) # 3.14
print(float("inf")) # inf (无穷大)
# 转换为字符串
print(str(10)) # "10"
print(str(3.14)) # "3.14"
print(str(True)) # "True"
print(str([1, 2, 3])) # "[1, 2, 3]"
# 转换为布尔值
print(bool(0)) # False
print(bool(1)) # True
print(bool("")) # False
print(bool("hello")) # True
print(bool([])) # False
print(bool([1])) # True
print(bool(None)) # False
# 转换为列表
print(list("hello")) # ['h', 'e', 'l', 'l', 'o']
print(list((1, 2, 3))) # [1, 2, 3]
print(list({1, 2, 3})) # [1, 2, 3]
print(list({"a": 1})) # ['a'] (只转换键)
# 转换为元组
print(tuple([1, 2, 3])) # (1, 2, 3)
print(tuple("hello")) # ('h', 'e', 'l', 'l', 'o')
# 转换为集合
print(set([1, 2, 2, 3])) # {1, 2, 3} (自动去重)
print(set("hello")) # {'h', 'e', 'l', 'o'}
# 转换为字典
pairs = [("a", 1), ("b", 2)]
print(dict(pairs)) # {'a': 1, 'b': 2}
安全的类型转换
# 使用try-except处理转换错误
def safe_int(value):
try:
return int(value)
except (ValueError, TypeError):
return None
print(safe_int("10")) # 10
print(safe_int("abc")) # None
print(safe_int(None)) # None
# 用户输入的类型转换
try:
age = int(input("请输入年龄: "))
print(f"你的年龄是: {age}")
except ValueError:
print("输入无效,请输入一个整数")
可变与不可变类型
不可变类型(Immutable)
一旦创建就不能修改的对象:
- int
- float
- complex
- str
- tuple
- bool
- NoneType
- frozenset
# 字符串是不可变的
text = "Hello"
# text[0] = "h" # ❌ TypeError
# "修改"字符串实际上是创建新对象
text = text.lower()
print(id(text)) # 内存地址改变了
# 元组是不可变的
tup = (1, 2, 3)
# tup[0] = 10 # ❌ TypeError
# 但元组中包含可变对象时,可变对象可以修改
tup_with_list = (1, 2, [3, 4])
tup_with_list[2].append(5)
print(tup_with_list) # (1, 2, [3, 4, 5])
可变类型(Mutable)
可以原地修改的对象:
- list
- dict
- set
- bytearray
# 列表是可变的
fruits = ["apple", "banana"]
print(id(fruits)) # 内存地址
fruits.append("orange")
print(id(fruits)) # 内存地址不变(同一个对象)
print(fruits) # ['apple', 'banana', 'orange']
# 字典是可变的
user = {"name": "Alice"}
print(id(user))
user["age"] = 25
print(id(user)) # 内存地址不变
print(user) # {'name': 'Alice', 'age': 25}
可变对象的陷阱
# 陷阱1:多个变量引用同一个对象
list1 = [1, 2, 3]
list2 = list1 # list2和list1指向同一个列表
list2.append(4)
print(list1) # [1, 2, 3, 4] (被影响了!)
# 解决方案:创建副本
list1 = [1, 2, 3]
list2 = list1.copy() # 或 list2 = list1[:]
list2.append(4)
print(list1) # [1, 2, 3] (不受影响)
# 陷阱2:默认参数使用可变对象
def add_item(item, items=[]): # ❌ 危险!
items.append(item)
return items
print(add_item(1)) # [1]
print(add_item(2)) # [1, 2] (不是预期的[2]!)
# 正确的做法
def add_item(item, items=None): # ✓ 安全
if items is None:
items = []
items.append(item)
return items
print(add_item(1)) # [1]
print(add_item(2)) # [2]
数据类型选择指南
何时使用哪种数据类型?
# 1. 存储单个值
- 整数: count, age, index
- 浮点数: price, temperature, score
- 字符串: name, message, address
- 布尔值: is_active, has_permission
# 2. 存储有序集合
- 列表: 需要频繁增删改的元素集合
>>> fruits = ["apple", "banana", "orange"]
- 元组: 固定的、不应修改的数据
>>> coordinates = (10, 20)
>>> RGB_color = (255, 128, 0)
# 3. 存储键值对
- 字典: 需要通过键快速查找值
>>> user = {"name": "Alice", "age": 25}
# 4. 存储唯一元素集合
- 集合: 去重、集合运算
>>> unique_ids = {1, 2, 3, 4, 5}
# 5. 表示空值
- None: 变量尚未赋值或函数无返回值
>>> result = None
性能考虑
import time
# 成员测试性能比较
my_list = list(range(10000))
my_set = set(range(10000))
# 列表: O(n)
start = time.time()
9999 in my_list
end = time.time()
print(f"List: {end - start:.6f}秒")
# 集合: O(1)
start = time.time()
9999 in my_set
end = time.time()
print(f"Set: {end - start:.6f}秒")
# 集合快得多!
实战示例
示例1:学生成绩管理系统
"""学生成绩管理系统"""
class StudentGradeSystem:
def __init__(self):
self.students = {} # {学号: {姓名, 成绩}}
def add_student(self, student_id: str, name: str) -> None:
"""添加学生"""
if student_id in self.students:
print(f"学生 {student_id} 已存在")
return
self.students[student_id] = {
"name": name,
"grades": {}
}
print(f"学生 {name} 添加成功")
def add_grade(self, student_id: str, subject: str, grade: float) -> None:
"""添加成绩"""
if student_id not in self.students:
print(f"学生 {student_id} 不存在")
return
if not 0 <= grade <= 100:
print("成绩必须在0-100之间")
return
self.students[student_id]["grades"][subject] = grade
print(f"成绩添加成功: {subject} = {grade}")
def get_average(self, student_id: str) -> float:
"""计算平均分"""
if student_id not in self.students:
return 0.0
grades = self.students[student_id]["grades"].values()
if not grades:
return 0.0
return sum(grades) / len(grades)
def get_top_students(self, n: int = 3) -> list:
"""获取前N名学生"""
if not self.students:
return []
student_averages = []
for student_id, info in self.students.items():
avg = self.get_average(student_id)
student_averages.append({
"id": student_id,
"name": info["name"],
"average": avg
})
# 按平均分降序排序
student_averages.sort(key=lambda x: x["average"], reverse=True)
return student_averages[:n]
def display_report(self) -> None:
"""显示成绩报告"""
print("\n" + "="*60)
print("学生成绩报告")
print("="*60)
for student_id, info in self.students.items():
print(f"\n学号: {student_id}")
print(f"姓名: {info['name']}")
if info["grades"]:
print("成绩:")
for subject, grade in info["grades"].items():
print(f" {subject}: {grade}")
avg = self.get_average(student_id)
print(f"平均分: {avg:.2f}")
else:
print("暂无成绩")
print("\n" + "="*60)
print("前三名學生:")
top_students = self.get_top_students(3)
for i, student in enumerate(top_students, 1):
print(f"{i}. {student['name']} (平均分: {student['average']:.2f})")
print("="*60)
# 使用示例
system = StudentGradeSystem()
system.add_student("001", "张三")
system.add_student("002", "李四")
system.add_student("003", "王五")
system.add_grade("001", "数学", 90)
system.add_grade("001", "英语", 85)
system.add_grade("002", "数学", 78)
system.add_grade("002", "英语", 92)
system.add_grade("003", "数学", 95)
system.add_grade("003", "英语", 88)
system.display_report()
示例2:数据分析工具
"""简单数据分析工具"""
class DataAnalyzer:
def __init__(self, data: list[float]):
self.data = data
def mean(self) -> float:
"""计算平均值"""
if not self.data:
return 0.0
return sum(self.data) / len(self.data)
def median(self) -> float:
"""计算中位数"""
if not self.data:
return 0.0
sorted_data = sorted(self.data)
n = len(sorted_data)
mid = n // 2
if n % 2 == 0:
return (sorted_data[mid - 1] + sorted_data[mid]) / 2
else:
return sorted_data[mid]
def mode(self) -> list:
"""计算众数"""
if not self.data:
return []
from collections import Counter
counter = Counter(self.data)
max_count = max(counter.values())
modes = [num for num, count in counter.items() if count == max_count]
return modes
def variance(self) -> float:
"""计算方差"""
if len(self.data) < 2:
return 0.0
mean = self.mean()
squared_diffs = [(x - mean) ** 2 for x in self.data]
return sum(squared_diffs) / (len(self.data) - 1)
def std_dev(self) -> float:
"""计算标准差"""
return self.variance() ** 0.5
def min_max(self) -> tuple:
"""返回最小值和最大值"""
if not self.data:
return (None, None)
return (min(self.data), max(self.data))
def summary(self) -> dict:
"""生成数据摘要"""
return {
"count": len(self.data),
"mean": round(self.mean(), 2),
"median": self.median(),
"mode": self.mode(),
"min": min(self.data) if self.data else None,
"max": max(self.data) if self.data else None,
"variance": round(self.variance(), 2),
"std_dev": round(self.std_dev(), 2)
}
def display_summary(self) -> None:
"""显示数据摘要"""
summary = self.summary()
print("\n" + "="*40)
print("数据统计摘要")
print("="*40)
print(f"数据个数: {summary['count']}")
print(f"平均值: {summary['mean']}")
print(f"中位数: {summary['median']}")
print(f"众数: {summary['mode']}")
print(f"最小值: {summary['min']}")
print(f"最大值: {summary['max']}")
print(f"方差: {summary['variance']}")
print(f"标准差: {summary['std_dev']}")
print("="*40)
# 使用示例
data = [85, 92, 78, 65, 90, 88, 72, 95, 60, 82, 92, 88]
analyzer = DataAnalyzer(data)
analyzer.display_summary()
示例3:购物车系统
"""购物车系统"""
class ShoppingCart:
def __init__(self):
self.items = {} # {商品名: {"price": 价格, "quantity": 数量}}
def add_item(self, name: str, price: float, quantity: int = 1) -> None:
"""添加商品"""
if price < 0 or quantity < 0:
raise ValueError("价格和数量必须为非负数")
if name in self.items:
self.items[name]["quantity"] += quantity
else:
self.items[name] = {
"price": price,
"quantity": quantity
}
print(f"已添加: {name} x{quantity}")
def remove_item(self, name: str) -> None:
"""移除商品"""
if name in self.items:
del self.items[name]
print(f"已移除: {name}")
else:
print(f"商品不存在: {name}")
def update_quantity(self, name: str, quantity: int) -> None:
"""更新商品数量"""
if name not in self.items:
print(f"商品不存在: {name}")
return
if quantity <= 0:
self.remove_item(name)
else:
self.items[name]["quantity"] = quantity
print(f"已更新 {name} 数量为 {quantity}")
def get_total(self) -> float:
"""计算总价"""
total = 0.0
for item in self.items.values():
total += item["price"] * item["quantity"]
return total
def get_item_count(self) -> int:
"""获取商品种类数"""
return len(self.items)
def get_total_quantity(self) -> int:
"""获取商品总数量"""
return sum(item["quantity"] for item in self.items.values())
def display_cart(self) -> None:
"""显示购物车"""
if not self.items:
print("购物车为空")
return
print("\n" + "="*50)
print("购物车内容")
print("="*50)
for name, info in self.items.items():
subtotal = info["price"] * info["quantity"]
print(f"{name}")
print(f" 单价: ¥{info['price']:.2f}")
print(f" 数量: {info['quantity']}")
print(f" 小计: ¥{subtotal:.2f}")
print()
print("-"*50)
print(f"商品种类: {self.get_item_count()}")
print(f"商品总数: {self.get_total_quantity()}")
print(f"总计: ¥{self.get_total():.2f}")
print("="*50)
# 使用示例
cart = ShoppingCart()
cart.add_item("苹果", 5.5, 3)
cart.add_item("香蕉", 3.0, 2)
cart.add_item("牛奶", 12.0)
cart.add_item("苹果", 5.5, 2) # 增加苹果数量
cart.display_cart()
cart.update_quantity("香蕉", 5)
cart.display_cart()
cart.remove_item("牛奶")
cart.display_cart()
总结
核心要点
-
Python是动态类型语言: 变量不需要声明类型,解释器自动推断
-
主要数据类型:
- 数值: int, float, complex
- 文本: str
- 逻辑: bool
- 空值: None
- 序列: list, tuple
- 映射: dict
- 集合: set
-
可变vs不可变:
- 不可变: int, float, str, tuple, bool, None
- 可变: list, dict, set
- 理解这一点对避免bug至关重要
-
类型转换:
- 使用int(), float(), str(), bool()等函数
- 注意处理可能的ValueError
- 使用try-except进行安全转换
-
选择合适的数据类型:
- 有序且需修改 → list
- 有序且固定 → tuple
- 键值对 → dict
- 唯一元素 → set
- 文本 → str
-
最佳实践:
- 使用类型提示提高代码可读性
- 使用isinstance()而非type()进行类型检查
- 注意可变对象的引用问题
- 使用f-string进行字符串格式化
- 使用in操作符检查成员关系
常见错误
- ❌ 忽略浮点数精度问题
- ❌ 混淆可变和不可变类型
- ❌ 默认参数使用可变对象
- ❌ 使用== None而不是is None
- ❌ 忘记元组单元素需要逗号
- ❌ 用{}创建空集合(实际是空字典)
学习资源
记住: 选择正确的数据类型是编写高效、可维护代码的关键。理解每种数据类型的特点、优势和限制,将帮助你更好地解决编程问题。