1、 解压序列赋值给多个变量
>>> p = (4, 5) >>> x, y = p >>> x 4 >>> y 5 >>> data = [ 'ACME', 50, 91.1, (2012, 12, 21) ] >>> name, shares, price, date = data >>> name 'ACME' >>> date (2012, 12, 21) >>> name, shares, price, (year, mon, day) = data >>> name 'ACME' >>> year 2012 >>> mon 12 >>> day 21 >>> >>> name 'ACME' >>> year 2012 >>> mon 12 >>> day 21 >>>
如果变量个数和序列元素的个数不匹配,会产生一个异常。 代码示例:
>>> p = (4, 5) >>> x, y, z = p Traceback (most recent call last): File "<stdin>", line 1, in <module> ValueError: need more than 2 values to unpack >>>
2、解压可迭代对象赋值给多个变量
Python 的星号表达式可以用来解决这个问题。比如,你在学习一门课程,在学期 末的时候,你想统计下家庭作业的平均成绩,但是排除掉第一个和最后一个分数。如 果只有四个分数,你可能就直接去简单的手动赋值,但如果有 24 个呢?这时候星号表 达式就派上用场了。
def drop_first_last(grades): first, *middle, last = grades return avg(middle)
另外一种情况,假设你现在有一些用户的记录列表,每条记录包含一个名字、邮 件,接着就是不确定数量的电话号码。你可以像下面这样分解这些记录:
>>> record = ('Dave', 'dave@example.com', '773-555-1212', '847-555-1212') >>> name, email, *phone_numbers = record >>> name 'Dave' >>> email 'dave@example.com' >>> phone_numbers ['773-555-1212', '847-555-1212'] >>>
值得注意的是上面解压出的 phone numbers 变量永远都是列表类型,不管解压的 电话号码数量是多少 (包括 0 个)。所以,任何使用到 phone numbers 变量的代码就不 需要做多余的类型检查去确认它是否是列表类型了。
星号表达式也能用在列表的开始部分。比如,你有一个公司前 8 个月销售数据的序 列,但是你想看下最近一个月数据和前面 7 个月的平均值的对比。你可以这样做:
*trailing_qtrs, current_qtr = sales_record trailing_avg = sum(trailing_qtrs) / len(trailing_qtrs) return avg_comparison(trailing_avg, current_qtr)
下面是在 Python 解释器中执行的结果:
>>> *trailing, current = [10, 8, 7, 1, 9, 5, 10, 3] >>> trailing [10, 8, 7, 1, 9, 5, 10] >>> current 3
3、保留最后N个元素
# 保留最后 N 个元素( collections.deque 大显身手的时候。比如,下面的代码 在多行上面做简单的文本匹配,并返回匹配所在行的前 N 行:) from collections import deque def search(lines, pattern, history=5): previous_lines = deque(maxlen=history) for li in lines: if pattern in li: yield li, previous_lines previous_lines.append(li) if __name__ == '__main__': with open(r'../cookbook/somefile.txt') as f: for line, prevlines in search(f, 'python', 5): for pline in prevlines: print(pline, end='') print(line, end='') print('-' * 20) # 使用 deque(maxlen=N) 构造函数会新建一个固定大小的队列。 # 当新的元素加入并 且这个队列已满的时候,最老的元素会自动被移除掉。 q = deque(maxlen=2) q.append(1) q.append(2) q.append(3) print(q) # deque 类可以被用在任何你只需要一个简单队列数据结构的场合。如 果你不设置最大队列大小,那么就会得到一个无限大小队列,你可以在队列的两端执 行添加和弹出元素的操作 q.appendleft(4) q.pop() q.q.popleft() print(q)
4、查找最大或最小的N个元素
import heapq nums = [1, 8, 2, 23, 7, -4, 18, 23, 42, 37, 2] print(heapq.nlargest(3, nums)) # Prints [42, 37, 23] print(heapq.nsmallest(3, nums)) # Prints [-4, 1, 2] portfolio = [ {'name': 'IBM', 'shares': 100, 'price': 91.1}, {'name': 'AAPL', 'shares': 50, 'price': 543.22}, {'name': 'FB', 'shares': 200, 'price': 21.09}, {'name': 'HPQ', 'shares': 35, 'price': 31.75}, {'name': 'YHOO', 'shares': 45, 'price': 16.35}, {'name': 'ACME', 'shares': 75, 'price': 115.65} ] cheap = heapq.nsmallest(3, portfolio, key=lambda s: s['price']) expensive = heapq.nlargest(3, portfolio, key=lambda s: s['price']) print(cheap) print(expensive) # 堆数据结构最重要的特征是 heap[0] 永远是最小的元素。 # 并且剩余的元素可以很 容易的通过调用 heapq.heappop() 方法得到,该方法会先将第一个元素弹出来,然后用下一个最小的元素来取代被弹出元素 (这种操作时间复杂度仅仅是 O(log N),N 是 堆大小)。 # 比如,如果想要查找最小的元素,你可以这样做: nums = [1, 8, 2, 23, 7, -4, 18, 23, 42, 37, 2] import heapq heapq.heapify(nums) print(heapq.heappop(nums)) # 当要查找的元素个数相对比较小的时候,函数 nlargest() 和 nsmallest() 是很 合适的。 # 如果你仅仅想查找唯一的最小或最大 (N=1) 的元素的话,那么使用 min() 和 max() 函数会更快些。类似的,如果 N 的大小和集合大小接近的时候,通常先排序这 个集合然后再使用切片操作会更快点 ( sorted(items)[:N] 或者是 sorted(items)[-N:] )。 # 需要在正确场合使用函数 nlargest() 和 nsmallest() 才能发挥它们的优势 (如果 N 快接近集合
5、实现一个优先级队列
import heapq class PriorityQueue: def __init__(self): #类实例创建之后调用, 对当前对象的实例的一些初始化, 没有返回值 self._queue = [] self._index = 0 def push(self, item, priority): heapq.heappush(self._queue, (-priority, self._index, item)) self._index += 1 def pop(self): return heapq.heappop(self._queue)[-1] class Item: def __init__(self, name): self.name = name def __repr__(self): #返回一个可以用来表示对象的可打印字符串 return 'Item({!r})'.format(self.name) q = PriorityQueue() q.push(Item('foo'), 1) q.push(Item('bar'), 5) q.push(Item('spam'), 4) q.push(Item('grok'), 1) print(q.pop()) print(q.pop()) # 引入另外的 index 变量组成三元组 (priority, index, item) ,就能很好的 避免队列同级比较出错。 a = (1, 0, Item('foo')) c = (1, 2, Item('grok')) print(a < c)
6、字典中映射多个键值
# 字典中的键映射多个值 d = { 'a' : [1, 2, 3], 'b' : [4, 5] } e = { 'a' : {1, 2, 3}, 'b' : {4, 5} } # 选择使用列表还是集合取决于你的实际需求。 # 如果你想保持元素的插入顺序就应该 使用列表,如果想去掉重复元素就使用集合(并且不关心元素的顺序问题) # 你可以很方便的使用 collections 模块中的 defaultdict 来构造这样的字典。 # defaultdict 的一个特征是它会自动初始化每个 key 刚开始对应的值,所以你只需要 关注添加元素操作了。比如: from collections import defaultdict d = defaultdict(list) d['a'].append(1) d['a'].append(2) d['b'].append(4) print(d) d = defaultdict(set) d['a'].add(1) d['a'].add(2) d['b'].add(4) print(d) # defaultdict 会自动为将要访问的键 (就算目前字典中并不存在这 样的键) 创建映射实体。 # 如果你并不需要这样的特性,你可以在一个普通的字典上使用 setdefault() 方法来代替。比如: d = {} # A regular dictionary d .setdefault('a', []).append(1) d .setdefault('a', []).append(2) d .setdefault('b', []).append(4) print(d) # 创建一个多值映射字典 pairs={'a':[22,44],'b':[88]} d = defaultdict(list) for key, value in e.items(): d[key].append(value) print(d)
7、字典排序
from collections import OrderedDict # 控 制 一 个 字 典 中 元 素 的 顺 序, 你 可 以 使 用 collections 模 块 中 的 OrderedDict 类。 # 在迭代操作的时候它会保持元素被插入时的顺序 d = OrderedDict() def ordered_dict(): d['foo'] = 1 d['bar'] = 2 d['spam'] = 3 d['grok'] = 4 # Outputs "foo 1", "bar 2", "spam 3", "grok 4" for key in d: print(key, d[key]) ordered_dict() # 当你想要构建一个将来需要序列化或编码成其他格式的映射的时候 import json print(json.dumps(d)) # OrderedDict 内部维护着一个根据键插入顺序排序的双向链表。 # 每次当一个新的元 素插入进来的时候,它会被放到链表的尾部。 # 对于一个已经存在的键的重复赋值不会 改变键的顺序。 # 需要注意的是,一个 OrderedDict 的大小是一个普通字典的两倍,因为它内部维 护着另外一个链表。 # 所以如果你要构建一个需要大量 OrderedDict 实例的数据结构的 时候 (比如读取 100,000 行 CSV 数据到一个 OrderedDict 列表中去),那么你就得仔细 权衡一下是否使用 OrderedDict 带来的好处要大过额外内存消耗的影响。 # python 对字典"排序" x={2:1,3:4,4:2,1:5,5:3} import operator sorted_x=sorted(x.items(),key=operator.itemgetter(0))#按照item中的第key:0,或者value:1进行排序 # 字典始终都按照key从小到大排序,与定义过程无关,转化为list嵌套tuple这里也依然按着key排序,, print(x) print(sorted_x) # 如果想按照倒序排序的话,则只要将reverse置为true即可。 sorted_y=sorted(x.keys(),reverse=True) print(sorted_y)
8、字典运算
# 为了对字典值执行计算操作,通常需要使用 zip() 函数先将键和值反转过来 prices = { 'ACME': 45.23, 'AAPL': 612.78, 'IBM': 205.55, 'HPQ': 37.20, 'FB': 10.75 } min_price = min(zip(prices.values(), prices.keys())) print(min_price) # min_prise is (10.75, 'FB') max_price = max(zip(prices.values(), prices.keys())) print(max_price) # max_price is (612.78, 'AAPL') # 类似的,可以使用 zip() 和 sorted() 函数来按值来排列字典数据 prices_sorted = sorted(zip(prices.values(), prices.keys())) print(prices_sorted) # prices_sorted is [(10.75, 'FB'), (37.2, 'HPQ'), # (45.23, 'ACME'), (205.55, 'IBM'), # (612.78, 'AAPL')] ###################################################### # 执行这些计算的时候,需要注意的是 zip() 函数创建的是一个只能访问一次的迭 代器。 prices_and_names = zip(prices.values(), prices.keys()) print(min(prices_and_names)) # OK 最小的价格和名字 (10.75, 'FB') # print(max(prices_and_names)) 这行就会报错,因为prices_and_names只能访问一次。 ############################################################# # 如果你在一个字典上执行普通的数学运算,你会发现它们仅仅作用于键,而不是值 print(min(prices)) # Returns 'AAPL' print(max(prices))# Returns 'IBM' print(min(prices.values())) # Returns 10.75 print(max(prices.values())) # Returns 612.78 # # 不幸的是,通常这个结果同样也不是你想要的。你可能还想要知道对应的键的信息 # # # 你可以在 min() 和 max() 函数中提供 key 函数参数来获取最小值或最大值对应的 键的信息。比如: # print(min(prices, key=lambda k: prices[k])) # Returns 'FB print(max(prices, key=lambda k: prices[k])) # Returns 'AAPL' ################################################################### # 需要注意的是在计算操作中使用到了 (值,键) 对。当多个实体拥有相同的值的时 候,键会决定返回结果。 # 比如,在执行 min() 和 max() 操作的时候,如果恰巧最小或 最大值有重复的,那么拥有最小或最大键的实体会返回: prices = { 'AAA' : 45.23, 'ZZZ': 45.23 } print(min(zip(prices.values(), prices.keys()))) # (45.23, 'AAA') print(max(zip(prices.values(), prices.keys()))) #(45.23, 'ZZZ')
9、查找两字典的相同点
a = { 'x' : 1, 'y' : 2, 'z' : 3 } b = { 'w' : 10, 'x' : 11, 'y' : 2 } # 为了寻找两个字典的相同点,可以简单的在两字典的 keys() 或者 items() 方法返 回结果上执行集合操作。 # 寻找相同的key print(a.keys() & b.keys()) # { 'x', 'y' } # 输出a中不在b中的key print(a.keys() - b.keys()) # { 'z' } # 查找(键,值)对完全相同的 print(a.items() & b.items() )# { ('y', 2) } # 修改或者过滤字典元素 # 制作一个新的字典,删除某些键 c = {key:a[key] for key in a.keys() - {'z', 'w'}} print(c) #{'y': 2, 'x': 1}
10、删除序列中相同元素并保持顺序
# 如果你想基于单个字段、属性或者某个更大的数据结构来消除重复元素 c = list(dedupe(a, key=lambda d: d['x'])) print(c) # 如果你仅仅就是想消除重复元素,通常可以简单的构造一个集合,不能保证顺序 d = [1, 5, 2, 1, 9, 1, 5, 10] print(set(d)) ################################### # 过滤工具就是itertools.compress() ,它以一个 iterable 对象和一个相对应的 Boolean 选择器序列作为输入参数。 # 然后输出 iterable 对象中 对应选择器为 True 的元素 addresses = [ '5412 N CLARK', '5148 N CLARK', '5800 E 58TH', '2122 N CLARK' '5645 N RAVENSWOOD', '1060 W ADDISON', '4801 N BROADWAY', '1039 W GRANVILLE', ] counts = [ 0, 3, 10, 4, 1, 7, 6, 1] # 现在你想将那些对应 count 值大于 5 的地址全部输出 from itertools import compress more5 = [n > 5 for n in counts] print(more5) #[False, False, True, False, False, True, True, False] print(list(compress(addresses, more5))) #['5800 E 58TH', '4801 N BROADWAY', '1039 W GRANVILLE'] # 这里的关键点在于先创建一个 Boolean 序列,指示哪些元素复合条件。 # 然后 compress() 函数根据这个序列去选择输出对应位置为 True 的元素
11、命名切片
# 你的程序已经出现一大堆已无法直视的硬编码切片下标,然后你想清理下代码 # 假定你有一段代码要从一个记录字符串中几个固定位置提取出特定的数据字段 # 通常一个切片操作要提供三个参数 [start_index: stop_index: step] # start_index是切片的起始位置 # stop_index是切片的结束位置(不包括) # step可以不提供,默认值是1,步长值不能为0,不然会报错ValueError。 # 当 step 是负数时,以[start_index]元素位置开始, # step做为步长到[stop_index]元素位置(不包括)为止,从右向左截取, # start_index和stop_index不论是正数还是负数索引还是混用都可以, # 但是要保证 list[stop_index]元素的【逻辑】位置 # 必须在list[start_index]元素的【逻辑】位置左边,否则取不出元素。 # 另外start_index和stop_index都是可以省略的, # 比如这样的形式 [:], 被省略的默认由其对应左右边界起始元素开始截取。 # 切片;[0:3] 索引0开始取,直到索引3为止,但不包括索引3 #[-3:]获取列表的后3个元素,[:] ,[0:]获取所有元素 #指定增长步长 [0:101:10] 从索引0 到索引101,没间隔10个索引取出一个值。10为步长 record = '....................100 .......513.25 ..........' cost = int(record[20:23]) * float(record[31:37]) print(cost) # 命名切片,你避免了大量无法理解的硬编码下标,使得你的代码更加清晰可读 SHARES = slice(20, 23) PRICE = slice(31, 37) cost = int(record[SHARES]) * float(record[PRICE]) a = slice(5, 50, 2) print(a.start) print(a.stop) print(a.step) # 如果你有一个切片对象 a,你可以分别调用它的 a.start , a.stop , a.step 属性来 获取更多的信息。 # 还能通过调用切片的 indices(size) 方法将它映射到一个确定大小的序 列上,这个方法返回一个三元组 (start, stop, step) , # 所有值都会被合适的缩小以 满足边界限制,从而使用的时候避免出现 IndexError 异常 s = 'HelloWorld' print(a.indices(len(s))) for i in range(*a.indices(len(s))): print(s[i]) alist = [0, 1, 2, 3, 4, 5, 6, 7, 8, 9] print(alist[-1:1:-1]) print(alist[-5:]) print(alist[:5]) # 取奇数位置元素 print(alist[1::2]) # https://blog.csdn.net/xpresslink/article/details/77727507
12、序列中出现最多的元素
words = [ 'look', 'into', 'my', 'eyes', 'look', 'into', 'my', 'eyes', 'the', 'eyes', 'the', 'eyes', 'the', 'eyes', 'not', 'around', 'the', 'eyes', "don't", 'look', 'around', 'the', 'eyes', 'look', 'into', 'my', 'eyes', "you're", 'under' ] from collections import Counter word_counts = Counter(words) # 出现频率最高的 3 个单词 top_three = word_counts.most_common(3) print(top_three) # 作为输入, Counter 对象可以接受任意的 hashable 序列对象。在底层实现上,一 个 Counter 对象就是一个字典,将元素映射到它出现的次数上 print(word_counts['not'] ) # 如果你想手动增加计数,可以简单的用加法 morewords = ['why','are','you','not','looking','in','my','eyes'] for word in morewords: word_counts[word] += 1 print(word_counts['eyes']) # eyes在words中出现的次数 # Counter 实例一个鲜为人知的特性是它们可以很容易的跟数学运算操作相结合 a = Counter(words) print(a) b = Counter(morewords) print(a+b ) print(a-b) # Counter 对象在几乎所有需要制表或者计数数据的场合是非常有用的
13、通过关键字排序一个字典列表
rows = [ {'fname': 'Brian', 'lname': 'Jones', 'uid': 1003}, {'fname': 'David', 'lname': 'Beazley', 'uid': 1002}, {'fname': 'John', 'lname': 'Cleese', 'uid': 1001}, {'fname': 'Big', 'lname': 'Jones', 'uid': 1004} ] # 一个字典列表,你想根据某个或某几个字典字段来排序这个列表 from operator import itemgetter rows_by_fname = sorted(rows, key=itemgetter('fname')) rows_by_uid = sorted(rows, key=itemgetter('uid')) print(rows_by_fname) print(rows_by_uid) # itemgetter() 函数也支持多个 keys rows_by_lfname = sorted(rows, key=itemgetter('lname','fname')) print(rows_by_lfname) # 第二种方式用lambda表达式,效率会慢些 rows_by_fname = sorted(rows, key=lambda r: r['fname']) rows_by_lfname = sorted(rows, key=lambda r: (r['lname'],r['fname'])) # 同样适用这两个函数 print(min(rows, key=itemgetter('uid'))) print(max(rows, key=itemgetter('uid')))
14、排序不支持原生比较的对象
class User: def __init__(self, user_id): self.user_id = user_id def __repr__(self): return 'User({})'.format(self.user_id) # 内置的 sorted() 函数有一个关键字参数 key ,可以传入一个 callable 对象给它, # 这个 callable 对象对每个传入的对象返回一个值,这个值会被 sorted 用来排序这些 对象 from operator import attrgetter def sort_notcompare(): users = [User(23), User(3), User(99)] print(users) # print(sorted(users, key=lambda u: u.user_id)) #第一种方式.利用lambda表达式 print( sorted(users, key=attrgetter('user_id'))) #第二种方式可以不借助lambda表达式,借助operator。建议使用这种 sort_notcompare()
15、通过某个字段将记录分组
class User: def __init__(self, user_id): self.user_id = user_id def __repr__(self): return 'User({})'.format(self.user_id) # 内置的 sorted() 函数有一个关键字参数 key ,可以传入一个 callable 对象给它, # 这个 callable 对象对每个传入的对象返回一个值,这个值会被 sorted 用来排序这些 对象 from operator import attrgetter def sort_notcompare(): users = [User(23), User(3), User(99)] print(users) # print(sorted(users, key=lambda u: u.user_id)) #第一种方式.利用lambda表达式 print( sorted(users, key=attrgetter('user_id'))) #第二种方式可以不借助lambda表达式,借助operator。建议使用这种 sort_notcompare()
16、过滤序列元素
mylist = [1, 4, -5, 10, -7, 2, 3, -1] # 最简单的过滤序列元素的方法就是使用列表推导,会产生大量结果集,占用内存 #会直接生成列表 print([n for n in mylist if n > 0]) print([n for n in mylist if n < 0]) # 可以使用生成器表达式迭代产生过滤的元素.pos打印不出来,只能通过迭代成为单个元素。 pos = (n for n in mylist if n > 0) for x in pos: print(x) # 列表推导和生成器表达式通常情况下是过滤数据最简单的方式,在过滤的时候还能进行转换和计算。 mylist = [1, 4, -5, 10, -7, 2, 3, -1] import math print([math.sqrt(n) for n in mylist if n > 0]) # 过滤操作的一个变种就是将不符合条件的值用新的值代替,而不是丢弃它们 # 列表中小于零的值用零来填充 clip_neg = [n if n > 0 else 0 for n in mylist] print(clip_neg) clip_pos = [n if n < 0 else 0 for n in mylist] print(clip_pos)
17、从字典中提取子集
prices = { 'ACME': 45.23, 'AAPL': 612.78, 'IBM': 205.55, 'HPQ': 37.20, 'FB': 10.75 } # 制作所有价格超过200的字典 p1 = {key: value for key, value in prices.items() if value > 200} print(p1) # 制作包含tech_names key的字典 tech_names = {'AAPL', 'IBM', 'HPQ', 'MSFT'} p2 = {key: value for key, value in prices.items() if key in tech_names} print(p2)
18、映射名称到序列元素
# 你有一段通过下标访问列表或者元组中元素的代码, # 但是这样有时候会使得你的代 码难以阅读,于是你想通过名称来访问元素。 # collections.namedtuple() 函数通过使用一个普通的元组对象来帮你解决这个问 题 from collections import namedtuple Subscriber = namedtuple('Subscriber', ['addr', 'joined']) sub = Subscriber('jonesy@example.com', '2012-10-19') print(sub) print(sub.addr) print(sub.joined) # 尽管 namedtuple 的实例看起来像一个普通的类实例, # 但是它跟元组类型是可交换 的,支持所有的普通元组操作,比如索引和解压 print(len(sub)) addr, joined = sub print(sub) print(joined)
19、转换并同时计算数据
import os nums = [1, 2, 3, 4, 5] s = sum(x * x for x in nums) print(s) # Determine if any .py files exist in a directory import os files = os.listdir('E:\virtualenvztloo\testscrapy\base') if any(name.endswith('.py') for name in files): print('There be python!') else: print('Sorry, no python.') # Output a tuple as CSV s = ('ACME', 50, 123.45) print(','.join(str(x) for x in s)) # Data reduction across fields of a data structure portfolio = [ {'name':'GOOG', 'shares': 50}, {'name':'YHOO', 'shares': 75}, {'name':'AOL', 'shares': 20}, {'name':'SCOX', 'shares': 65} ] min_shares = min(s['shares'] for s in portfolio) print(min_shares)
20、合并多个字典或映射
a = {'x': 1, 'z': 3 } b = {'y': 2, 'z': 4 } from collections import ChainMap c = ChainMap(a,b) print(c['x']) # Outputs 1 (from a) print(c['y']) # Outputs 2 (from b) print(c['z']) # Outputs 3 (from a) # 个 ChainMap 接受多个字典并将它们在逻辑上变为一个字典。然后,这些字典并 不是真的合并在一起了, ChainMap 类只是在内部创建了一个容纳这些字典的列表并重 新定义了一些常见的字典操作来遍历这个列表。 # 大部分字典操作都是可以正常使用的 print(len(c)) print(list(c.keys())) print(list(c.values())) # 如果出现重复键,那么第一次出现的映射值会被返回。 # 因此,例子程序中的 c['z'] 总是会返回字典 a 中对应的值,而不是 b 中对应的值。 # 对于字典的更新或删除操作总是影响的是列表中第一个字典。 c['z'] = 10 c['w'] = 40 del c['x'] print(a) # del c['y'] #报错 因为第一个字典中没有y # ChainMap 对于编程语言中的作用范围变量 (比如 globals , locals 等) 是非常有用 的。 # 事实上,有一些方法可以使它变得简单: values = ChainMap() values['x'] = 1 # Add a new mapping values = values.new_child() values['x'] = 2 # Add a new mapping values = values.new_child() values['x'] = 3 print(values) #ChainMap({'x': 3}, {'x': 2}, {'x': 1}) print(values['x']) #输出3 # Discard last mapping values = values.parents print(values['x']) #输出2 # Discard last mapping values = values.parents print(values['x']) #输出1 print(values) #输出ChainMap({'x': 1}) # 作为 ChainMap 的替代,你可能会考虑使用 update() 方法将两个字典合并. # 这样也能行得通,但是它需要你创建一个完全不同的字典对象 (或者是破坏现有字 典结构)。 # 同时,如果原字典做了更新,这种改变不会反应到新的合并字典中去 a = {'x': 1, 'z': 3 } b = {'y': 2, 'z': 4 } merged = dict(b) merged.update(a) print(merged['x']) print(merged['y']) print(merged['z']) a['x'] = 13 print(merged['x']) # ChainMap 使用原来的字典,它自己不创建新的字典。所以它并不会产生上面所说 的结果,比如: a = {'x': 1, 'z': 3 } b = {'y': 2, 'z': 4 } merged = ChainMap(a, b) merged['x'] a['x'] = 42 print(merged['x'])