title: Python 奇技淫巧date: 2021-02-08 12:47:59
tags: Python
categories: Python

{% cq %} 总结的关于 Python 的一些魔法和技巧。 {% endcq %}

1. 处理输入

1.1 输入三个数字

map 方法返回的是可迭代对象,可以直接用三个变量接收。

  1. # 输入:1 2 3
  2. a, b, c = map(int, input().split())

1.2 输入一组数字

将 map 返回的对象用 list() 函数转换成列表,完成输入。

  1. # 输入:1 2 3 4 5
  2. nums = list(map(int, input().split()))

2. 将字符串打印出 n 次

  1. n = 5
  2. ch = "hello"
  3. print(n * ch)
  4. # 输出:hellohellohellohellohello

3. 合并字典的 5 种方法

3.1 update 方法

使用内置方法 update() 原地操作。

  1. dct1.update(dtc2)

3.2 ** 解包

使用 ** 解包字典,之后直接用 dict(){} 将其合并。

  1. dct3 = {**dct1, **dct2}

3.3 items 合并

使用 items 方法将字典转成 dict_items 对象,然后取并集 |,最后可直接用 dict() 函数转成字典。

  1. dct3 = dict(dct1.items() | dct2.items())

3.4 字典解析式

  1. dct3 = {k:v for d in [dct1, dct2] for k, v in d.items()}

3.5 字典合并操作符

Python3.9 提供了合并操作符 |,可直接将两个字典合并。在此之前,| 运算符一般用于集合的求并运算。

  1. dct3 = dct1 | dct2

原地操作

  1. dct1 |= dct2

4. 合并列表的 5 种方法

4.1 直接相加

  1. ls3 = ls1 + ls2

4.2 extend 方法

extend 方法是在列表末尾追加另一个序列中的所有元素。

  1. ls1.extend(ls2)

4.3 * 解包大法

直接使用 ls3 = [ls1, ls2] 的方法会合成一个子序列的列表,可用 * 解包再合并。

  1. ls3 = [*ls1, *ls2]

4.4 万能的列表推导式

是的,列表推导式也能用于合并列表。

  1. ls3 = [i for ls in (ls1, ls2) for i in ls]

4.5 使用 heapq

heaqp 是 Python 内置的模块,heapq.merge 方法用于多个列表的合并,并将其堆排序。

  1. import heapq
  2. lst = heapq.merge(ls1, ls2, ls3)

5. 平铺多维列表

这里的多为维表就是指嵌套的列表,维度是指嵌套层数的最大值。比如二维列表 [1,[2,3],4],三维列表[1,[2,[3,4]],5] 等。

5.1 平铺二维列表

  1. lst = [1, [2,3], [4, 5], 6]
  2. def spread1(ls):
  3. ans = []
  4. for i in ls:
  5. if isinstance(i, list):
  6. ans.extend(i)
  7. else:
  8. ans.append(i)
  9. return ans
  10. spread1(lst)
  11. # ans: [1, 2, 3, 4, 5, 6]

5.2 平铺任意维度列表

方法一(递归):很容易想到递归方法,实现如下。

  1. lst = [1, [2, [3]], [[4, [5, 6]], 7], [8, 9], 10]
  2. def spread2(lst, res=None):
  3. if res is None:
  4. res = []
  5. for item in lst:
  6. if isinstance(item, list):
  7. spread2(item, res)
  8. else:
  9. res.append(item)
  10. return res
  11. spread(lst)
  12. # res: [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]

方法二(迭代):递归易于理解,但是需要函数调用栈而降低效率,可以使用迭代(循环)代替。

  1. def spred3(lst):
  2. res = []
  3. while lst:
  4. head = lst.pop(0)
  5. if isinstance(head, list):
  6. lst = head + lst
  7. else:
  8. res.append(head)
  9. return res

6. 将两个列表合并为字典

  1. a = [1, 2, 3]
  2. b = ['a', 'b', 'c']
  3. dct = dict(zip(a,b))
  4. # dtc = {1: 'a', 2: 'b', 3: 'c'}

7. 求列表中出现次数最多/少的元素

maxmin 有一个参数 key,可指定求最大/小时的依据。

  1. nums = [1,1,2,2,2,3]
  2. max_freq = max(set(nums), key=nums.count)
  3. min_freq = min(set(nums), key=nums.count)

8. 交换两个变量的值

原理是将 x 与 y 封装在一个元组内 (y, x),然后再按照位序赋值给 x,y。

  1. x, y = y, x

9. 链式比较

对于 x >= 1 and x <= 10,我们可以简写为 1 <= x <= 10,这就是所谓的链式对比。
现在来看一个问题,试判断以下的真假?

  1. True == True == False

是不是很难判断,但结合上述的链式比较,这个式子可以转化为:

  1. True == True and True == False

现在结果一目了然了,返回值是 False

持续更新…