目录
4、用支持插值的 f-string
5、用辅助函数取代复杂的表达式
6、把数据结构直接拆分到多个变量里,不要专门通过下标访问
7、尽量用 enumerate 取代 range
8、用 zip 函数同时遍历两个迭代器
4、用支持插值的 f-string
- f-string是个简洁而强大的机制,可以直接在格式说明符里嵌入任意Python表达式。
key = 'my_var'
value = 1.234
formatted = f'{key!r:<10} = {value:.2f}'
print(formatted)
-------------------------------------------
>>> 'my_var' = 1.23
places = 3
number = 1.23456
print(f'My number is {number:.{places}f}')
--------------------------------------------
>>> My number is 1.235
5、用辅助函数取代复杂的表达式
- 尤其是重复使用的复杂表达式,应该写到辅助函数里面。
- 用 if / else 结构写成的条件表达式,要比用 or 与 and 写成的 Boolean 表达式更好懂。
- dict_name.get(key_name, exception_to_return) 的方式可以返回不存在的键,并返回设定的值。
def get_first_int(values, key, default=0):
found = values.get(key, [''])
if found[0]:
return int(found[0])
return default
6、把数据结构直接拆分到多个变量里,不要专门通过下标访问
- 凡是可迭代的对象都能拆分,无论里面还有多少层迭代结构。
- 尽量通过 unpacking 来拆解序列之中的数据。
item = ('Peanut butter', 'Jelly')
first, second = item # 左边可以是list, sequence, iterable
print(first, 'and', second)
-------------------------------------------------------------
>>> Peanut butter and Jelly
7、尽量用 enumerate 取代 range
- 可以通过 enumerate 的第二个参数指定起始序号(默认为0)
- enumerate 能把任何一种 iterator 封装成 lazy generator,每次循环的时候,只需要从 iterator 里面获取下一个值就可以,同时还会给出本轮循环的序号。可以通过内置的 next 函数手动推进 enumerate 所返回的这个 iterator。next(enumerate(flavor_list))
for i, flavor in enumerate(flavor_list):
print(f'{i + 1}: {flavor}')
for i, flavor in enumerate(flavor_list, 1):
print(f'{i}: {flavor}')
--------------------------------------------
>>> 1: vanilla
2: chocolate
3: pecan
4: strawberry
8、用 zip 函数同时遍历两个迭代器
- 如果无法确定列表的长度相同,就不要传给 zip,而是传给 zip_longest 函数,这个函数位于内置的 itertools 模块里。
- zip 函数能够把两个或更多的 iterator 封装成 lazy generator,每次循环时,会分别从这些迭代器里获取各自的下一个元素,并把这些值放在一个元组里面,而这个元组可以拆分到 for 语句里那些变量中。
- zip 每次只从它封装的那些迭代器里各自取出一个元素,所以即便源列表很长,程序也不会因为占用内存过多而崩溃。
- 如果提供的迭代器长度不一致,其中任何一个完毕,zip 就会停止。
for name, count in zip(names, counts):
if count > max_count:
longest_name = name
max_count = count
import itertools
for name, count in itertools.zip_longest(names, counts):
print(f'{name}: {count}')
9、不要在 for 与 while 循环后面写 else 块
- for / else 结构里的 else,如果循环从头到尾执行完,那就执行 else 块。在循环中使用 break 语句实际上会跳过 else 块。
- 如果对空白序列做 for 循环,那么程序立刻就会执行 else 块。
- while 循环同上,首次循环就遇到 False,会立刻执行 else 块。
- 如果把 else 块紧跟在 for / while 的后面,就会让代码产生歧义。
a = 4
b = 9
for i in range(2, min(a, b) + 1):
print('Testing', i)
if a % i == 0 and b % i == 0:
print('Not coprime')
break
else:
print('Coprime')
-------------------------------------
>>> Testing 2
Testing 3
Testing 4
Coprime
|