Python 一句话代码技巧(二)

文章目录

使用 sum() 函数或 list.count() 方法统计数量

sum() 函数的常规用法是求一个可迭代对象里面各元素的和(如果可求和的话)。当然,如果我们对一个只有 1 和 0 的列表求和,那么就可以求出列表中 1 的数量。根据这个思路,我们可以先将待处理的列表转换为一个仅存储布尔值的列表,再对其求和,就可以统计出其中满足条件元素的数量。例如还是上一篇文章中的例子:

1value = 7
2count = 0
3lst = [1, 1, 4, 5, 1, 4, 1, 9, 1, 9, 8, 10]
4for i in lst:
5    if i > value:
6        count += 1
7print(count)
8
9# output: 4

我们结合推导式创建一个新的列表,将满足条件的存储为 1,这样再求和。

1print(sum(1 if i > 7 else 0 for i in [1, 1, 4, 5, 1, 4, 1, 9, 1, 9, 8, 10]))
2# 如果只有 if 语句,则将 if 语句放到 for 后。如果是 if-else 三元表达式,则将 if-else 前置。
3# 也可以写成
4print([1 for i in [1, 1, 4, 5, 1, 4, 1, 9, 1, 9, 8, 10] if i > 7].count(1))
5# 或者
6print(len([1 for i in [1, 1, 4, 5, 1, 4, 1, 9, 1, 9, 8, 10] if i > 7]))
7
8# output: 4

map() 函数

map() 函数的定义为 map(func, *iterables) --> map boject,该函数将一个可变对象中的每一个元素传入函数中做操作,并将每一个返回值存储到一个 map 对象中,这个 map 对象可以被转换为一个新的可迭代对象,也可以将其作为参数传给其他接受迭代器的函数。

下面这行代码示例可以将输入的内容转化为整形并存储到列表中

1result = list(map(int, input().split(' ')))

再例如下面这个例子,统计字符串中不重复的英文字符:

1print(set(map(str.upper, "Hello, World!")))
2
3# output: {'L', 'O', '!', 'E', 'R', 'D', 'H', ' ', 'W', ','}

求平方数:

1def suqare(n):
2	return n ** 2
3
4print(sorted(map(square, [4, 3, 2, 5])))
5
6# output: [4, 9, 16, 25]

zip() 函数

zip() 函数可以依次将多个可迭代对象合并到元组,并返回一个 zip 对象。zip 对象可以被转换为列表、字典、元组、集合。

1print(list(zip(['a', 'b', 'c'], [1, 2, 3], ['A', 'B', 'C'])))
2
3# output: [('a', 1, 'A'), ('b', 2, 'B'), ('c', 3, 'C')]

将数据打包成字典:

1keys = ['name', 'age']
2values = ['Jane Doe', '18']
3print(dict(zip(keys, values)))
4
5# output: {'name': 'Jane Doe', 'age': '18'}

该函数还能够便捷求出矩阵的转置:

 1matrix = [
 2	[1, 2, 3],
 3	[4, 5, 6],
 4	[7, 8, 9]
 5]
 6
 7print(*map(list, zip(*matrix)), sep='\n')
 8
 9"""
10output:
11[1, 4, 7]
12[2, 5, 8]
13[3, 6, 9]
14"""

使用 enumerate() 函数简化 for 循环

enumerate() 函数定义是 enumerate(iterable, start=0),该函数可以用更便捷的方法于创建迭代器,在某些情境下优于 range() 函数。例如说,一个经典的 for 循环写法如下:

 1codes = ['alpha', 'bravo', 'charlie']
 2i = 0
 3for code in codes:
 4	print(i, code)
 5	i += 1
 6
 7"""
 8output:
 90 alpha
101 bravo
112 charlie
12"""

使用 enumerate() 可以简化这段代码:

 1codes = ['alpha', 'bravo', 'charlie']
 2for i, code in enumerate(codes):
 3	print(i, code)
 4
 5"""
 6output:
 70 alpha
 81 bravo
 92 charlie
10"""

或者直接简化成一行:

1print(*[f"{i} {code}" for i, code in enumerate(['alpha', 'bravo', 'charlie'])], sep='\n')
2
3"""
4output:
50 alpha
61 bravo
72 charlie
8"""

可以使用 enumerate() 函数创建带有序号的字典:

1print(dict(enumerate(["Spring", "Summer", "Autumn", "Winter"], start=1)))
2
3# output: {1: 'Spring', 2: 'Summer', 3: 'Autumn', 4: 'Winter'}

或者配合 zip() 函数在循环中添加更多内容:

 1performers = ["Alice", "Bob", "Charles", "Daniel"]
 2performances = ["Singing", "Dancing", "Rapping", "Basketball Showcase"]
 3for i, (performer, performance) in enumerate(zip(performers, performances), start=1):
 4	print("Sequence: {:02} Performer: {} Performance: {}".format(i, performer, performance))
 5
 6"""
 7output:
 8Sequence: 01 Performer: Alice Performance: Singing
 9Sequence: 02 Performer: Bob Performance: Dancing
10Sequence: 03 Performer: Charles Performance: Rapping
11Sequence: 04 Performer: Daniel Performance: Basketball Showcase
12"""

next() 函数快速匹配内容

next() 函数的用法如下:

 1it = iter(range(1, 5))
 2while True:
 3	x = next(it, False)
 4	print(x)
 5	if not x:
 6		break
 7
 8"""
 9output:
101
112
123
134
14False
15"""

如果不给 next() 传入第二个参数,也可以使用 StopIteration 终止循环。

 1it = iter(range(1, 5))
 2while True:
 3	try:
 4		x = next(it)
 5		print(x)
 6	except StopIteration:
 7		break
 8
 9"""
10output:
111
122
133
144
15"""

例如说,我们想要在下面的列表中找到第一个符合要求的内容,就可以用 next() 函数。

1names = ["Alice", "Bob", "Charles"]
2scores = [80, 90, 100]
3data = zip(names, scores)
4print(next((i for i in data if i[1] == 100), None))
5
6# output: ('Charles', 100)

如果在可迭代对象中有多个元素符合条件,则 next() 函数会找出第一个符合条件的元素。

 1names = ["Alice", "Bob", "Charles"]
 2scores = [80, 90, 100]
 3data = zip(names, scores)
 4print(next((i for i in data if i[1] > 80), None))
 5print(next((i for i in data if i[1] > 80), None))
 6print(next((i for i in data if i[1] > 80), None))
 7print(next((i for i in data if i[1] > 80), None))
 8
 9"""
10output:
11('Bob', 90)
12('Charles', 100)
13None
14None
15"""

不难发现,next() 函数每次输出的内容都是建立在上一个 next() 函数执行结果之后的,也就是说每次 next() 是对同一个可迭代对象操作。如果像每次都输出相同内容,可以将 zip 对象转化为列表:

1names = ["Alice", "Bob", "Charles"]
2scores = [80, 90, 100]
3data = list(zip(names, scores))
4print(next((i for i in data if i[1] > 80), None))
5print(next((i for i in data if i[1] > 80), None))
6
7# output:
8# ('Bob', 90)
9# ('Bob', 90)

或者使用一个生成可迭代对象的函数:

 1def my_generator():
 2	names = ["Alice", "Bob", "Charles"]
 3	scores = [80, 90, 100]
 4	data = zip(names, scores)
 5	for i in data:
 6		if i[1] > 80:
 7			yield i
 8
 9print(next(my_generator(), None))
10print(next(my_generator(), None))
11
12# output:
13# ('Bob', 90)
14# ('Bob', 90)

next() 的执行效率高于循环,在日常编程中该函数也是不二之选。

filter() 快速筛选

上面 next() 函数一次只能返回一个元素,而 filter() 函数会一次性返回所有符合条件的元素

1def f(x):
2	return x > 7
3
4print(tuple(filter(f, [1, 1, 4, 5, 1, 4, 1, 9, 1, 9, 8, 10])))
5
6# output: (9, 9, 8, 10)
1def f(x):
2	return x[1] > 80
3
4names = ["Alice", "Bob", "Charles"]
5scores = [80, 90, 100]
6data = dict(zip(names, scores))
7print(list(filter(f, data.items())))
8
9# output: [('Bob', 90), ('Charles', 100)]

any()all()

这两个函数接收可迭代对象作为参数,如果可迭代对象中有任意一个元素的布尔值为 True,则 any() 函数返回 True;如果可迭代对象中每一个元素的布尔值都为 True,则 all() 函数返回 True

1print(any(["", [], (), None]))  # 这些对象的布尔值都是 False 
2print(any(["Hello", [1, 1, 4, 5, 1, 4], False]))
3
4# output:
5# False
6# True
1print(all([{True, False}, True]))
2print(all(['A', False]))
3
4# output:
5# True
6# False

相关系列文章