defmanual_str_formatting(name, subscribers):
if subscribers > 100000:
print("Wow " + name + "! you have " + str(subscribers) + " subscribers!")
else:
print("Lol " + name + " that's not many subs")
使用 + 号拼接字符串效率较低,且代码可读性差,尤其是变量较多时。
好的做法:
defmanual_str_formatting(name, subscribers):
# betterif subscribers > 100000:
print(f"Wow {name}! you have {subscribers} subscribers!")
else:
print(f"Lol {name} that's not many subs")
deffinally_instead_of_context_manager(host, port):
# close even if exceptionwith socket.socket(socket.AF_INET, socket.SOCK_STREAM) as s:
s.connect((host, port))
s.sendall(b'Hello, world')
使用上下文管理器(with 语句),即使发生异常,也会自动关闭 socket,代码更简洁安全。
3、尝试手动关闭文件
坏的做法:
defmanually_calling_close_on_a_file(filename):
f = open(filename, "w")
f.write("hello!\n")
f.close()
手动调用 close() 容易忘记,或者在异常发生时导致文件未正确关闭。
好的做法:
defmanually_calling_close_on_a_file(filename):
withopen(filename) as f:
f.write("hello!\n")
# close automatic, even if exception
使用上下文管理器打开文件,即使发生异常,文件也会自动关闭,这是处理文件 IO 的首选方式。
4、except 后面什么也不写
坏的做法:
defbare_except():
whileTrue:
try:
s = input("Input a number: ")
x = int(s)
breakexcept: # oops! can't CTRL-C to exitprint("Not a number, try again")
捕获所有异常会导致无法通过 CTRL-C 终止程序,且可能掩盖真正的错误。
好的做法:
defbare_except():
whileTrue:
try:
s = input("Input a number: ")
x = int(s)
breakexcept Exception: # 比这更好的是用 ValueErrorprint("Not a number, try again")
defmutable_default_arguments():
defappend(n, l=None):
if l isNone:
l = []
l.append(n)
return l
l1 = append(0) # [0]
l2 = append(1) # [1]
将默认参数设为 None,在函数内部初始化可变对象,确保每次调用都有独立的实例。
6、从不用推导式
坏的做法:
squares = {}
for i inrange(10):
squares[i] = i * i
使用循环构建字典或列表比较冗长,不够直观。
好的做法:
odd_squares = {i: i * i for i inrange(10)}
列表推导式和字典推导式是 Python 的特色语法,能显著减少代码行数并提高可读性。
7、推导式用的上瘾
坏的做法:
c = [
sum(a[n * i + k] * b[n * k + j] for k inrange(n))
for i inrange(n)
for j inrange(n)
]
过度嵌套的推导式会降低代码可读性,增加维护难度。
好的做法:
c = []
for i inrange(n):
for j inrange(n):
ij_entry = sum(a[n * i + k] * b[n * k + j] for k inrange(n))
c.append(ij_entry)
当逻辑复杂时,应优先保证可读性,使用常规循环替代复杂的推导式。
8、检查类型是否一致用 ==
坏的做法:
defchecking_type_equality():
Point = namedtuple('Point', ['x', 'y'])
p = Point(1, 2)
iftype(p) == tuple:
print("it's a tuple")
else:
print("it's not a tuple")
使用 type() == 判断类型不推荐,因为它不支持继承关系检查。
好的做法:
defchecking_type_equality():
Point = namedtuple('Point', ['x', 'y'])
p = Point(1, 2)
# probably meant to check if is instance of tupleifisinstance(p, tuple):
print("it's a tuple")
else:
print("it's not a tuple")
使用 isinstance() 可以正确处理继承和多态情况,是标准的类型检查方法。
9、用 == 判断是否单例
坏的做法:
defequality_for_singletons(x):
if x == None:
passif x == True:
passif x == False:
pass
对于单例对象(如 None, True, False),使用 == 比较值而非身份。
好的做法:
defequality_for_singletons(x):
# betterif x isNone:
passif x isTrue:
passif x isFalse:
pass
defchecking_bool_or_len(x):
# usually equivalent toif x:
pass
Python 中的布尔上下文会自动处理真值测试,直接使用变量即可。
11、使用类 C 风格的 for 循环
坏的做法:
defrange_len_pattern():
a = [1, 2, 3]
for i inrange(len(a)):
v = a[i]
...
b = [4, 5, 6]
for i inrange(len(b)):
av = a[i]
bv = b[i]
...
使用索引遍历列表是 C/Java 风格,在 Python 中不够优雅。
好的做法:
defrange_len_pattern():
a = [1, 2, 3]
# insteadfor v in a:
...
# or if you wanted the indexfor i, v inenumerate(a):
...
# instead use zipfor av, bv inzip(a, b):
...
直接迭代元素、使用 enumerate 获取索引、或使用 zip 并行迭代,更符合 Python 习惯。
12、不实用 dict.items
坏的做法:
defnot_using_dict_items():
d = {"a": 1, "b": 2, "c": 3}
for key in d:
val = d[key]
...
遍历字典键再取值效率低且代码啰嗦。
好的做法:
defnot_using_dict_items():
d = {"a": 1, "b": 2, "c": 3}
for key, val in d.items():
...
defnot_using_numpy_pandas():
x = list(range(100))
y = list(range(100))
s = [a + b for a, b inzip(x, y)]
```\n纯 Python 列表处理数值计算效率低下,缺乏向量化能力。
**好的做法:**
```python
import numpy as np
defnot_using_numpy_pandas():
# 性能更快
x = np.arange(100)
y = np.arange(100)
s = x + y
使用 NumPy 进行数组运算,利用底层 C 实现,性能大幅提升。
18、喜欢 import *
坏的做法:
from itertools import *
count()
通配符导入污染命名空间,导致变量来源不明,增加冲突风险。
好的做法:
from mypackage.nearby_module import awesome_function
defmain():
awesome_function()
if __name__ == '__main__':
main()