容器运算#

1. 合并#

1.1. 解包合并#

list01 = [1, 2, 3]
list02 = [4, 5, 6]
list03 = [*list01, *list02]
print("list03", list03)
# [1, 2, 3, 4, 5, 6]

profile = {"name": "xiaoming", "age": 27}
ext_info = {"gender": "male"}

full_profile01 = {**profile, **ext_info}
print(full_profile01)
# {'name': 'xiaoming', 'age': 27, 'gender': 'male'}

1.2. 内置方法#

list01 = [1, 2, 3]
list02 = [4, 5, 6]

list01.extend(list02)
print("list01", list01)
# [1, 2, 3, 4, 5, 6]
list03 = list01 + list02
print("list03", list03)
# [1, 2, 3, 4, 5, 6]

["a"]*10
# ['a', 'a', 'a', 'a', 'a', 'a', 'a', 'a', 'a', 'a']

profile = {"name": "xiaoming", "age": 27}
ext_info = {"gender": "male"}

profile.update(ext_info)
print(profile)
# {'name': 'xiaoming', 'age': 27, 'gender': 'male'}
new = profile | ext_info
print(new)
# {'name': 'xiaoming', 'age': 27, 'gender': 'male'}

1.3. 增量运算#

对列表 进行 += 操作相当于 extend,而使用 =+ 操作是新增了一个列表。

  • += 其背后使用的魔法方法是 __iadd__ ,若没有实现这个方法则会退而求其次,使用 __add__ 。用列表举例 a += b ,使用 __add__ 的话就像是使用了 a.extend(b) ,若使用 __add__ 的话,则是 a = a + b ,前者是直接在原列表上进行扩展,而后者是先从原列表中取出值,在一个新的列表中进行扩展,然后再将新的列表对象返回给变量,显然后者的消耗要大些。

  • 在遇到不可变序列时,增量运算会在背后生成新的序列。

# +=
a = [1, 2, 3, 4]
b = a
a += [5, 6, 7, 8]
print("a", a) # [1, 2, 3, 4, 5, 6, 7, 8]
print("b", b) # [1, 2, 3, 4, 5, 6, 7, 8]

# =+
a = [1, 2, 3, 4]
b = a
a = a + [5, 6, 7, 8]
print("a", a) # [1, 2, 3, 4, 5, 6, 7, 8]
print("b", b) # [1, 2, 3, 4]

# Find keys in common
a.keys() & b.keys() # { 'x', 'y' }
# Find (key, value) pairs in common
a.items() & b.items() # { ('y', 2) }
# Find keys in a that are not in b
a.keys() - b.keys() # { 'z' }

2. 配对#

x, y = [1, 2, 3], [4, 5, 6]
zipped = zip(x, y)
[*zipped] # [(1, 4), (2, 5), (3, 6)]

from itertools import zip_longest

x, y =[1, 2], [3]
[*zip_longest(x, y)] # [(1, 3), (2, None)]

3. 排序#

3.1. 关键字排序#

sort() 对字符串的大小写敏感,可指定 key 来避免这种影响。

  • sort() 返回值即自身,故无法被接收。

  • - 可对数值类型逆序。

  • 对多个不同类型的 key 排序,需要分步进行。

places = ["home", "work", "New York", "Paris"]
places.sort()
print("Case sensitive:  ", places)
places.sort(key=lambda x: x.lower())
print("Case insensitive:", places)

3.2. 迭代排序#

sorted(iterable, key, reverse=False) 对可迭代对象排序,无返回值。

# 绝对值排序
print(sorted([36, 5, -12, 9, -21], key=abs))

# 字符串排序
print(sorted(["bob", "about", "Zoo", "Credit"], key=str.lower))

# 按 value 排序
L = [("Bob", 75), ("Adam", 92), ("Bart", 66), ("Lisa", 88)]
d = dict(L)
print(sorted(d.items(), key=lambda x: x[1]))

对字典或 JSON 用 operator.itemgetter() 通常会运行得更快一些。这个同样适用于 min()max() 这样的函数。

3.3. 合并排序#

heapq 模块里有一个 merge 方法,可以用于合并多个列表。

from heapq import merge

list01 = [1, 2, 3]
list02 = [4, 5, 6]
list03 = [7, 8, 9]

list04 = [*merge(list01, list02, list03)] # [1, 2, 3, 4, 5, 6, 7, 8, 9]
print("list04", list04)

4. 高阶函数#

Python 中有 3 个常用的迭代函数,其本质均为生成器。是由于引入了列表推导和生成器表达式,它 们变得没那么重要了。

4.1. map#

map(func, iterable1, iterable2) 将传入的函数依次作用到序列的每个元素,并把结果迭代返回生成器对象。

# 函数需要一个参数
l = map(lambda x: x * x, [1, 2, 3])
print([*l])


#函数需要两个参数
def f1(x, y):
    return x, y


l1 = [0, 1, 2, 3, 4, 5, 6]
l2 = ["Sun", "M", "T", "W", "T", "F", "S"]
l3 = map(f1, l1, l2)
print([*l3])

4.2. filter#

filter(func/None, iterable) ,删除非 True 的内容,返回生成器对象。

# 判断奇数
l1 = filter(lambda x: x % 2, [1, 2, 3, 4])
print([*l1])

# 字符串判定
l2 = filter(None, "she")
print([*l2])

4.3. reduce#

reduce(func, iterable/value) 把一个函数作用在一个序列上,把结果继续和序列的下一个元素递归累加。

reduce(f, [x1, x2, x3, x4]) = f(f(f(x1, x2), x3), x4)

from functools import reduce

l1 = reduce(lambda x, y: x + y, [1, 2, 3, 4], 5)
print(l1)
l2 = reduce(lambda x, y: x + y, ["aa", "bb", "cc"], "dd")
print(l2)

5. 其他#

5.1. 二分查找#

import bisect


def grade(score, breakpoints=[60, 70, 80, 90], grades='FDCBA'):
    i = bisect.bisect(breakpoints, score)
    return grades[i]


[grade(score) for score in [33, 99, 77, 70, 89, 90, 100]
 ]  # ['F', 'A', 'C', 'C', 'B', 'A', 'A']

5.2. 插入#

import bisect
import random

SIZE = 7
random.seed(1729)
my_list = []

for i in range(SIZE):
    new_item = random.randrange(SIZE * 2)
    bisect.insort(my_list, new_item)
    print('%2d ->' % new_item, my_list)

5.3. 不可变映射类型#

from types import MappingProxyType

d = {1: 'A'}
d_proxy = MappingProxyType(d)
d_proxy
# mappingproxy({1: 'A'})
d_proxy[1]
# 'A'
d_proxy[2] = 'x'
# Traceback (most recent call last):
#  File "<stdin>", line 1, in <module>
# TypeError: 'mappingproxy' object does not support item assignment
d[2] = 'B'
d_proxy
# mappingproxy({1: 'A', 2: 'B'})
d_proxy[2]
# 'B'