08 Python字典(dict)完全指南

08 Python字典(dict)完全指南

1. 字典的基本概念字典(dict)是Python中的一种可变映射类型,它使用键值对(key-value pair)的形式来存储数据。字典的特点包括:

键(key)必须是不可变类型(如字符串、数字或元组)值(value)可以是任意Python对象键必须是唯一的Python 3.7+版本中字典会保持插入顺序2. 字典的创建方法代码语言:javascript复制# 1. 使用花括号创建

# 最常用的创建方式,直观且灵活

# 可以在创建时直接初始化多个键值对

# 支持嵌套字典结构

student = {

'name': '张三', # 字符串类型的键值对

'age': 20, # 数字类型的值

'scores': {'语文': 85, '数学': 92} # 嵌套字典

}

# 2. 使用dict()构造函数

# 适用于键名符合变量命名规则的情况

# 代码更简洁,但不支持复杂的键名

info = dict(name='李四', age=22) # 等同于 {'name': '李四', 'age': 22}

# 3. 使用字典推导式

# 适合批量创建有规律的键值对

# 代码简洁,可读性好

squares = {x: x**2 for x in range(5)} # 创建数字及其平方的映射

# 4. 使用dict.fromkeys()创建具有默认值的字典

# 适合初始化具有相同默认值的多个键

# 注意:所有键会共享同一个默认值对象

keys = ['a', 'b', 'c']

default_dict = dict.fromkeys(keys, 0) # 创建所有键对应值为0的字典3. 字典的基本操作3.1 访问和修改元素代码语言:javascript复制# 创建示例字典

user = {

'name': '张三',

'age': 25,

'email': 'zhangsan@example.com'

}

# 1. 访问元素的多种方式

# 使用方括号访问 - 最直接的方式,但键不存在时会抛出KeyError

print(user['name']) # 输出:张三

# 使用get()方法访问 - 推荐的安全访问方式

# 第一个参数是键名,第二个参数是键不存在时的默认值

age = user.get('age', 0) # 如果'age'键不存在,返回默认值0

phone = user.get('phone', '未设置') # 获取可能不存在的键

# 2. 修改元素

# 直接赋值修改已存在的键值对

user['age'] = 26 # 修改已存在的键的值

# 3. 添加新元素

# 使用新键直接赋值

user['phone'] = '13800138000' # 添加新的键值对

# 4. 删除元素的多种方式

# 使用del语句 - 删除指定键值对,键不存在会抛出KeyError

del user['email']

# 使用pop()方法 - 删除并返回值,可以提供默认值

phone = user.pop('phone', None) # 如果键不存在,返回None

# 使用popitem()方法 - 删除并返回最后一个键值对

last_item = user.popitem() # 返回元组(key, value)3.2 常用字典方法代码语言:javascript复制# 1. 获取字典信息的方法

# keys() - 获取所有键

# 返回一个动态视图对象,会随字典变化而更新

keys = user.keys() # 获取所有键的视图

key_list = list(keys) # 转换为列表

# values() - 获取所有值

# 同样返回动态视图对象

values = user.values() # 获取所有值的视图

value_list = list(values) # 转换为列表

# items() - 获取所有键值对

# 返回(key, value)元组的视图对象

items = user.items() # 获取所有键值对的视图

for key, value in items: # 常用于遍历字典

print(f"{key}: {value}")

# 2. 修改字典的方法

# update() - 批量更新字典

# 可以使用另一个字典或键值对序列更新

user.update({'city': '北京', 'age': 27}) # 使用字典更新

user.update(zip(['hobby', 'job'], ['读书', '程序员'])) # 使用键值对序列更新

# setdefault() - 设置默认值

# 如果键不存在,则设置默认值并返回

# 如果键存在,则返回现有值

email = user.setdefault('email', 'default@example.com')

# 3. 清理字典的方法

# clear() - 清空字典

# 删除所有键值对

user.clear() # 字典变为空字典 {}

# copy() - 创建字典的浅拷贝

# 创建新字典,但嵌套的可变对象仍然共享引用

user_copy = user.copy()4. 字典的高级应用4.1 嵌套字典代码语言:javascript复制# 复杂的嵌套字典示例

# 展示了多层嵌套的数据结构

# 适用于表示层级关系的数据

school = {

'class_1': {

'teacher': '王老师',

'students': {

'001': {

'name': '张三',

'scores': {'语文': 85, '数学': 92}

},

'002': {

'name': '李四',

'scores': {'语文': 89, '数学': 94}

}

}

}

}

# 访问嵌套数据的方法

# 1. 使用多级键访问

print(school['class_1']['students']['001']['scores']['语文']) # 输出:85

# 2. 使用get()方法的安全访问

# 避免键不存在时的异常

score = school.get('class_1', {}).get('students', {}).get('001', {}).get('scores', {}).get('语文', 0)

# 3. 修改嵌套数据

# 逐层创建或修改数据

school['class_2'] = {} # 创建新的班级

school['class_2']['teacher'] = '李老师' # 添加教师信息

school['class_2']['students'] = {} # 初始化学生字典4.2 字典推导式高级用法代码语言:javascript复制# 1. 条件字典推导式

# 根据条件筛选键值对

scores = {'张三': 85, '李四': 92, '王五': 78, '赵六': 95}

# 筛选成绩大于等于85分的学生

pass_students = {name: score for name, score in scores.items() if score >= 85}

# 2. 转换值的字典推导式

# 对原字典的值进行转换

grades = {name: 'A' if score >= 90 else 'B' if score >= 80 else 'C'

for name, score in scores.items()}

# 3. 嵌套字典推导式

# 创建复杂的嵌套字典结构

# 生成乘法表字典

matrix = {i: {j: i*j for j in range(3)} for i in range(3)}

# 结果示例:{0: {0: 0, 1: 0, 2: 0}, 1: {0: 0, 1: 1, 2: 2}, 2: {0: 0, 1: 2, 2: 4}}5. 使用字典格式化字符串5.1 基本格式化代码语言:javascript复制# 1. 使用%操作符(旧式格式化)

# 语法简单,但功能有限

info = {'name': '张三', 'age': 25}

print('%(name)s is %(age)d years old' % info)

# 2. 使用str.format()方法

# 更灵活,支持更多格式化选项

print('{name} is {age} years old'.format(**info))

# 3. 使用f-string(推荐,Python 3.6+)

# 最简洁、直观的方式

# 支持直接使用表达式

print(f"{info['name']} is {info['age']} years old")5.2 高级格式化技巧代码语言:javascript复制# 1. 对齐和填充

data = {'name': '张三', 'score': 95.5}

# 左对齐,宽度10

# 右对齐,宽度8,保留2位小数

print(f"{data['name']:<10}|{data['score']:>8.2f}")

# 2. 使用字典进行复杂模板格式化

# 适用于生成报告、配置文件等

template = '''

学生信息:

姓名:{name}

年龄:{age}

成绩:{score:.1f}

'''

student = {

'name': '张三',

'age': 18,

'score': 95.6

}

print(template.format(**student))6. 字典性能优化建议6.1 字典创建优化代码语言:javascript复制# 1. 预分配空间

# 当知道字典大小时,使用dict.fromkeys()预分配空间

# 避免频繁的内存重新分配

keys = range(10000)

optimized_dict = dict.fromkeys(keys) # 预分配10000个空间

# 对比:动态增长的字典

unoptimized_dict = {}

for i in range(10000):

unoptimized_dict[i] = None # 会导致多次内存重新分配

# 2. 使用字典推导式替代循环

# 字典推导式通常比循环创建字典更快

squares_comprehension = {x: x**2 for x in range(1000)} # 更快

squares_loop = {}

for x in range(1000): # 更慢

squares_loop[x] = x**26.2 访问优化代码语言:javascript复制# 1. 使用get()方法的最佳实践

# 当确定键存在时,使用方括号访问更快

user = {'name': '张三', 'age': 25}

# 快:确定键存在时使用方括号

name = user['name']

# 慢:不必要的get()调用

name = user.get('name')

# 正确使用场景:键可能不存在时使用get()

phone = user.get('phone', '未设置')

# 2. 避免重复访问

# 对频繁访问的值进行本地缓存

def process_user_slow(user):

# 差:重复访问字典

print(f"姓名:{user['name']}")

print(f"年龄:{user['age']}")

if user['age'] > 18:

print(f"{user['name']}是成年人")

def process_user_fast(user):

# 好:将频繁使用的值缓存到局部变量

name = user['name']

age = user['age']

print(f"姓名:{name}")

print(f"年龄:{age}")

if age > 18:

print(f"{name}是成年人")6.3 更新优化代码语言:javascript复制# 1. 批量更新优化

# 使用update()方法进行批量更新,而不是多次单独更新

user = {'name': '张三'}

# 差:多次单独更新

user['age'] = 25

user['city'] = '北京'

user['email'] = 'zhangsan@example.com'

# 好:使用update()批量更新

user.update({

'age': 25,

'city': '北京',

'email': 'zhangsan@example.com'

})

# 2. 避免频繁的增删操作

# 如果需要频繁增删,考虑使用collections.defaultdict或set

from collections import defaultdict

# 统计单词频率的例子

# 使用defaultdict避免键检查

word_counts = defaultdict(int)

text = "the quick brown fox jumps over the lazy dog"

for word in text.split():

word_counts[word] += 1 # 无需检查键是否存在6.4 内存优化代码语言:javascript复制# 1. 使用__slots__优化类字典

# 当类属性固定时,使用__slots__可以显著减少内存使用

class UserNormal:

def __init__(self, name, age):

self.name = name

self.age = age

class UserOptimized:

__slots__ = ['name', 'age'] # 显著减少内存使用

def __init__(self, name, age):

self.name = name

self.age = age

# 2. 及时清理不需要的数据

# 使用clear()方法而不是重新赋值

large_dict = {i: i**2 for i in range(10000)}

# 差:直接赋值新字典

large_dict = {} # 旧字典仍在内存中,等待垃圾回收

# 好:使用clear()清理

large_dict.clear() # 立即释放内存

# 3. 使用弱引用字典

# 当需要缓存对象但不阻止它们被垃圾回收时

from weakref import WeakKeyDictionary

class Cache:

def __init__(self):

# 当键对象没有其他引用时,自动从字典中删除

self.data = WeakKeyDictionary()6.5 性能测试示例代码语言:javascript复制import timeit

import sys

# 1. 字典创建性能对比

def test_dict_creation():

# 测试不同创建方法的性能

setup = """size = 1000"""

test1 = """dict_comp = {x: x**2 for x in range(size)}"""

test2 = """dict_loop = {}

for x in range(size):

dict_loop[x] = x**2"""

time1 = timeit.timeit(test1, setup, number=1000)

time2 = timeit.timeit(test2, setup, number=1000)

print(f"字典推导式: {time1:.4f}秒")

print(f"循环创建: {time2:.4f}秒")

# 2. 内存使用对比

def compare_memory_usage():

# 测试普通类和使用__slots__的类的内存占用

normal_users = [UserNormal(f"user{i}", i) for i in range(1000)]

optimized_users = [UserOptimized(f"user{i}", i) for i in range(1000)]

normal_size = sys.getsizeof(normal_users[0]) * len(normal_users)

optimized_size = sys.getsizeof(optimized_users[0]) * len(optimized_users)

print(f"普通类对象占用内存: {normal_size/1024:.2f}KB")

print(f"优化类对象占用内存: {optimized_size/1024:.2f}KB")

if __name__ == '__main__':

print("性能测试结果:")

test_dict_creation()

print("\n内存使用对比:")

compare_memory_usage()6.6 最佳实践总结 创建优化

预知大小时使用dict.fromkeys()预分配空间优先使用字典推导式而不是循环创建批量数据优先使用dict()构造函数 访问优化

确定键存在时使用方括号访问键可能不存在时才使用get()频繁访问的值存储在局部变量中 更新优化

多个键值对更新时使用update()频繁增删操作考虑使用defaultdict避免频繁的单键更新操作 内存优化

属性固定的类使用__slots__及时使用clear()释放内存合理使用弱引用字典避免存储重复数据 其他建议

使用适当的数据结构(如set代替值为None的字典)定期进行性能分析和内存监控在性能关键场景进行基准测试

相关推荐

beat365中文版 我叫汪革革什么时候播出

我叫汪革革什么时候播出

📅 08-25 👁️ 9314
365bet官方网 [文章]EdgeCAM是什么?关于EdgeCAM简介