master
/ 7.2.3 修改字典值.ipynb

7.2.3 修改字典值.ipynb @masterview markup · raw · history · blame

Notebook

修改字典值

字典是一种可变的数据类型,支持数据元素的增加、删除和修改操作。仍以通讯录为例,在使用的过程中,可能需要向数据里插入新的联系人数据、更新原有的联系人的姓名或电话、删除其中的数据。

元素值的修改与新增

  • ### 使用dict[key] = value方法

当键名key在字典中存在时,将修改字典dict中键key的值为新值value;

当键名key在字典中不存在时,将为字典增加以key为键,以value为值的新元素。

In [1]:
tel_book = {'李明': '13988887777', '张宏': '13866668888'}
# 键存在时更新
tel_book['李明'] = '13988887788'  # 李明的电话更新为 '13988887788'
tel_book['赵雪'] = '13000112222'  #新增元素 '赵雪': '13000112222'
print(tel_book)                   # {'李明': '13988887788', '张宏': '13866668888', '赵雪': '13000112222'}
{'李明': '13988887788', '张宏': '13866668888', '赵雪': '13000112222'}

  • ### 使用dict.update(k1=v1[, k2=v2,…])方法

可以用dict.update(k1=v1[, k2=v2,…])方法同时更新字典中的多个值:

当字典dict中存在k1、k2…时,将对应的值修改为v1、v2…;

当不存在相应的键值时,会将对应的k1:v1、k2:v2…键值对加入字典。

In [2]:
tel_book = {'李明': '13988887777', '张宏': '13866668888'}
# 将张宏的电话更新为'13866668877' ;'王晶'不存在,以键值对形式加入到字典中
tel_book.update(张宏='13866668877', 王晶='13244441111')  
print(tel_book)  # {'李明': '13988887777', '张宏': '13866668877', '王晶': '13244441111'}
{'李明': '13988887777', '张宏': '13866668877', '王晶': '13244441111'}

  • ### 使用dict.update([other])方法

接受另一个字典对象,或者一个包含键/值对(以长度为二的元组或其他可迭代对象表示)的可迭代对象。

当other中的键在字典dict中存在时,将修改为对应的值;

当other中的键在字典dict中不存在时,将键值对加入字典dict。

In [3]:
tel_book = {'李明': '13988887777', '张宏': '13866668888'}
tel_book2 = {'李明': '13988887788', '程钱': '13111223214'}
tel_book.update(tel_book2)
print(tel_book)
{'李明': '13988887788', '张宏': '13866668888', '程钱': '13111223214'}

In [10]:
tel_book = {'李明': '13988887777', '张宏': '13866668888'}
tel_book2 = [('李明', '13988887788'), ('程钱', '13111223214')]
tel_book.update(tel_book2)   # 也可使用包含键/值对(以长度为二的元组或其他可迭代对象表示)的可迭代对象
print(tel_book)

  • ### 使用dict.setdefault(key[, value])方法

当字典dict 中存在键key时,返回key对应的值;

键key不存在时,在字典中增加 key: value 键值对,值value缺省时,默认设其值为None。

In [11]:
tel_book = {'李明': '13988887777', '张宏': '13866668888'}
tel_book.setdefault('刘飞','13344556655')  # 为字典新增元素 '刘飞': '13344556655'
tel_book.setdefault(('程钱'))              # 值缺省时,默认为None,为字典新增元素'程钱': None
print(tel_book)
phone_number = tel_book.setdefault('李明') # 存在键'李明',返回其值'13988887777'
print(phone_number)

In [1]:
+ ### 使用运算符“|”和 “|=”
  File "/tmp/ipykernel_173/993078169.py", line 1
    + ### 使用运算符“|”和 “|=”
                        ^
SyntaxError: invalid syntax

Python 3.9 以后版本新增

d | other:合并 d 和 other 中的键和值来创建一个新的字典,两者必须都是字典。当 d 和 other 有相同键时, other 的值优先。

d |= other:用 other 的键和值更新字典 d ,other 可以是字典或可迭代的键值对。当 d 和 other 有相同键时, other 的值优先。

In [1]:
tel_book = {'李明': '13988887777', '张宏': '13866668888'}
tel_book2 = {'刘飞': '13344556655', '程钱': '13111223214'}
tel = tel_book | tel_book2
print(tel)

In [2]:
tel_book = {'李明': '13988887777', '张宏': '13866668888'}
tel_book2 = {'刘飞': '13344556655', '程钱': '13111223214'}
tel_book |= tel_book2 
print(tel_book)

字典元素的删除

  • ### 使用dict.pop(key[, default])方法

将键为 key 的键值对元素删除,返回值为键 key 对应的值;

如果提供了default 值,dict 中不存在 key 键时返回 default,否则将会触发“KeyValue”异常。

In [1]:
tel_book = {'李明': '13988887777', '张宏': '13866668888'}
del_key = tel_book.pop('张宏')
print('删除的联系人的电话是:', del_key)

In [2]:
tel_book = {'李明': '13988887777', '张宏': '13866668888'}
del_key = tel_book.pop('李宏', '用户不存在')
print('删除的联系人的电话是:', del_key)

In [3]:
tel_book = {'李明': '13988887777', '张宏': '13866668888'}
del_key = tel_book.pop('李宏')       # 未设置default 值,将会触发“KeyValue”异常
print('删除的联系人的电话是:', del_key)
  • ### 使用dict.popitem()方法

从字典中移除并返回一个元组形式的(键, 值) 对,

键值对会按LIFO(Last In, First Out, 后进先出)顺序被返回,即每次执行删除位于字典末尾的键值对。

In [4]:
tel_book = {'李明': '13988887777', '张宏': '13866668888'}
delitem = tel_book.popitem() 
print('删除的联系人是:',delitem)

如果字典为空,调用 popitem() 将引发 KeyError。

In [5]:
tel_book = {}
delitem = tel_book.popitem() 
print('删除的联系人是:',delitem)
  • ### 使用dict.clear()方法

清空字典dict中所有数据,保留空字典对象。

In [6]:
tel_book = {'李明': '13988887777', '张宏': '13866668888'}
tel_book.clear()  # 清空字典中的所有数据
print(tel_book)   # {}

  • ### 使用del dict[key]指令

将字典dict中键为key的键值对元素删除,如果不存在键key则会引发 KeyError。

In [7]:
tel_book = {'李明': '13988887777', '张宏': '13866668888'}
del tel_book['张宏']   # 删除键为'张宏'的键值对
print(tel_book)

In [8]:
tel_book = {'李明': '13988887777', '张宏': '13866668888'}
del tel_book['李小明']   # 键'李小明'不存在,引发KeyError
print(tel_book)
  • ### 使用del dict指令

将字典对象dict删除,后续如果再次引用该对象将引发NameError。

In [9]:
tel_book = {'李明': '13988887777', '张宏': '13866668888'}
del tel_book     # 删除名为tel_book的字典对象
print(tel_book)  # 触发NameError异常

“视图”可迭代数据

使用字典keys()、values()和items()方法生成的可迭代数据是一种特殊的“视图”类数据,这三个方法可以分别获得一个包含字典全部键、值和键值对的对象。
它们的值关联至原始字典,**当原始字典中的数据发生改变时,其值也会发生变化**

In [10]:
tel_book = {'李明': '13988887777', '张宏': '13866668888'}
ks = tel_book.keys()
vs = tel_book.values()
kvs = tel_book.items()
print(ks)    # dict_keys(['李明', '张宏'])
print(vs)    # dict_values(['13988887777', '13866668888'])
print(kvs) #dict_items([('李明', '13988887777'), ('张宏', '13866668888')])
tel_book.update(王晶='13244441111') #键‘王晶’不存在,将键值对加入字典
print(tel_book)  #{'李明': '13988887777', '张宏': '13866668888', '王晶': '13244441111'}
print(ks)   #print(ks)   dict_keys(['李明', '张宏', '王晶'])
print(vs)  #dict_values(['13988887777', '13866668888', '13244441111'])
print(kvs) #dict_items([('李明', '13988887777'), ('张宏', '13866668888'), ('王晶', '13244441111')])

Python 3.7版之后:,字典顺序会确保为插入顺序,因此这三个方法的返回值也按插入顺序,可以进行如下相关操作。

In [20]:
tel_book = {'李明': '13988887777', '张宏': '13866668888'}
ks = tel_book.keys()
vs = tel_book.values()
kvs = tel_book.items()
print(len(kvs))          # 可使用len()函数获取元素个数
print(list(zip(ks, vs))) # 允许使用zip()来创建 (值, 键) 对
print([(k, v) for (k, v) in kvs])      # 允许使用推导式来创建 (值, 键) 对
print(('李明', '13988887777') in kvs)  # 支持成员检测
print(list(reversed(kvs)))  # 支持逆序,返回一个逆序获取字典键、值或项的迭代器。

遍历字典时,若字典元素被删除,会导致字典长度发生变化而导致异常:

删除字典中特定元素

In [1]:
tel_book = {'李明': '13988887777', '张宏': '13866668888', '李小明': '13988886666', '李广': '13988885555', }

# 删除字典中姓“李”的人的元素
for user_name in tel_book:   # RuntimeError: dictionary changed size during iteration
    if user_name[0] == '李':
        tel_book.pop(user_name)
print(tel_book)

因字典的视图会随字典元素变化而发生变化,所以也不可以通过遍历字典视图的方法删除字典中的元素。

In [2]:
tel_book = {'李明': '13988887777', '张宏': '13866668888', '李小明': '13988886666', '李广': '13988885555', }

# 删除字典中姓“李”的人的元素
for user_name in tel_book.keys():   # RuntimeError: dictionary changed size during iteration
    if user_name[0] == '李':
        tel_book.pop(user_name)
print(tel_book)

为避免这个问题,推荐两个方法:

将字典的视图转为列表再用于控制遍历:

In [4]:
tel_book = {'李明': '13988887777', '张宏': '13866668888', '李小明': '13988886666', '李广': '13988885555', }

# 删除字典中姓“李”的人的元素
for user_name in list(tel_book.keys()):   # RuntimeError: dictionary changed size during iteration
    if user_name[0] == '李':
        tel_book.pop(user_name)
print(tel_book)

通过字典推导式的方法创建新的字典:

新字典元素是删除是过滤掉特定元素后的结果

In [5]:
tel_book = {'李明': '13988887777', '张宏': '13866668888', '李小明': '13988886666', '李广': '13988885555', }
# 删除字典中姓“李”的人的元素
tel_book_new = {x[0]: x[1] for x in tel_book.items() if x[0][0] != '李'}
print(tel_book_new)  # {'张宏': '13866668888'}

建议遍历时,直接用两个变量,可避免索引的使用,使程序更容易理解:

In [ ]:
tel_book = {'李明': '13988887777', '张宏': '13866668888', '李小明': '13988886666', '李广': '13988885555', }
# 删除字典中姓“李”的人的元素
tel_book_new = {k: v for k, v in tel_book.items() if k[0] != '李'}
print(tel_book_new)  # {'张宏': '13866668888'}