第三章 字典与集合

Python字典与集合详解

第3章 字典与集合

类和实例属性、模块命名空间、函数关键字参数等核心Python构造在内存中都是以字典形式表示。字典和集合的底层实现基于哈希表,这是它们高性能的关键。

字典现代操作

字典推导式

字典推导式通过任意可迭代对象中提取键值对来构建dict实例

# 示例3-1: 字典推导式
dial_codes = [
    (880, 'Bangladesh'),
    (55, 'Brazil'),
    (86, 'China'),
    (91, 'India'),
    (62, 'Indonesia'),
    (81, 'Japan'),
    (234, 'Nigeria'),
    (92, 'Pakistan'),
    (7, 'Russia'),
    (1, 'United States'),
]

# 交换键值对:country作为键,code作为值
country_dial = {
   
   country: code for code, country in dial_codes}

# 按国家名称排序,交换键值对,将值转为大写,并筛选出code < 70的项
filtered_codes = {
   
   
    code: country.upper()
    for country, code in sorted(country_dial.items())
    if code < 70
}

print("country_dial:", country_dial)
print("filtered_codes:", filtered_codes)

解包映射

# 在函数调用中对多个参数应用**解包
def dump(**kwargs):
    return kwargs
# 此时所有的键必须是唯一的字符串 在函数调用中,关键字参数本质上是命名参数
# 在 dump(**{'x': 1}, **{'x': 2})时会报错
# TypeError: dump() got multiple values for keyword argument 'x'
result1 = dump(**{
   
   'x': 1}, y=2, **{
   
   'z': 3})
print("dump result:", result1)  # 输出: {'x': 1, 'y': 2, 'z': 3}

# 进行字面量解包 此时允许重复的键 但后面的键会覆盖前面的键
# **解包可以多次使用
result2 = {
   
   'a': 0, **{
   
   'x': 1}, 'y': 2, **{
   
   'z': 3, 'x': 4}}
print("merged dict:", result2)  # 输出: {'a': 0, 'x': 4, 'y': 2, 'z': 3}

合并映射

# 使用|操作符合并映射(创建新映射)
d1 = {
   
   'a': 1, 'b': 3}
d2 = {
   
   'a': 2, 'b': 4, 'c': 6}
merged = d1 | d2
print("Merged with |:", merged)  # 输出: {'a': 2, 'b': 4, 'c': 6}

# 使用|=原地更新现有映射
d1 |= d2
print("d1 after |=:", d1)  # 输出: {'a': 2, 'b': 4, 'c': 6}
# 通常,新映射的类型与左操作数的类型相同,但涉及用户自定义类型时可能根据操作符重载规则采用右操作数的类型
# 此处涉及python重载类型的具体实现 以及类__or__的实现

模式匹配

match/case语句支持映射对象作为匹配主体,映射模式看起来像字典字面量,但可以匹配任何collections.abc.Mapping的具体子类或者虚拟子类。

def get_creators(record):
    """从媒体记录中提取创作者姓名"""
    match record:
        case {
   
   'type': 'book', 'api': 2, 'authors': [*names]}:
            return names
        case {
   
   'type': 'book', 'api': 1, 'author': name}:
            return [name]
        # 不符合上述匹配的type模式都是不合法的 报错
        case {
   
   'type': 'book'}:
            raise ValueError(f"Invalid 'book' record: {
     
     record!r}")
        case {
   
   'type': 'movie', 'director': name}:
            return [name]
        case _:
            raise ValueError(f'Invalid record: {
     
     record!r}')

# 测试示例
if __name__ == "__main__":
    # 测试书籍记录 (api=1)
    b1 = dict(api=1, author='Douglas Hofstadter',
              type='book', title='Gödel, Escher, Bach')
    print("Book 1 creators:", get_creators(b1))  # 输出: ['Douglas Hofstadter']
    
    # 测试书籍记录 (api=2)
    from collections import OrderedDict
    b2 = OrderedDict(api=2, type='book',
                     title='Python in a Nutshell',
                     authors='Martelli Ravenscroft Holden'.split())
    print("Book 2 creators:", get_creators(b2))  # 输出: ['Martelli', 'Ravenscroft', 'Holden']
    
    # 测试无效书籍记录
    try:
        get_creators({
   
   'type': 'book', 'pages': 770})
    except ValueError as e:
        print("Error:", str(e))
    
    # 测试非字典记录
    try:
        get_creators('Spam, spam, spam')
    except ValueError as e:
        print("Error:", str(e))
    
    # 测试捕获额外键值对
    food = dict(category='ice cream', flavor='vanilla', cost=199)
    match food:
        case {
   
   'category': 'ice cream', **details}:
            print(f"Ice cream details: {
     
     details
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值