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