Python是一门动态语言。动态性为Python带来了巨大的灵活性和表达力。但是任何事物都有两面性,动态性给Python带来强大能力的同时也带来了一些混乱,因此我们在开发过程中最好遵循某种最佳实践,以确保少犯错、不犯错。作为一个做了十几年Python开发的老鸟,为大家总结出5条Python开发最佳实践。
关于Python中常犯的错误、常掉的坑,我整理了另外一系列文章,大家可以移步到
Python避坑指南 和 Python避坑指南(续) 阅读。
不要用索引遍历序列
不要这样做
for i in range(len(tab)):
print(tab[i])
建议这样做
for elem in tab:
print(elem)
如果同时需要索引和元素,请用enumerate
for i, elem in enumerate(tab):
print((i, elem))
谨慎使用 "=="判断真假
if (var == True):
# 当var为True或1(包括1.0, 1L)时上面条件判断为True
if (var != True):
# 当var不为True或1时上面条件判断为True
if (var == False):
# 当var为False或0 (包括0.0, 0L, 0j)时上面条件判断为True
if (var == None):
# 当var为None时上面条件判断为True
if var:
# 当var为非空字符串/列表/字典/元组以及True和非0值时上面判断条件为True
if not var:
# 当var为 "", {}, [], (), 0, None, False时上面判断条件为True
if var is True:
# 当var为布尔值True时上面判断条件为True
if var is False:
# 当var为布尔值False时上面判断条件为True
if var is None:
# 当var为None时上面条件判断为True
善用错误处理
Python圈里有句至理名言:“请求宽恕易,请求许可难”("It's easier to ask for forgiveness than permission")
不要这样做
if os.path.isfile(file_path):
file = open(file_path)
else:
# do something
建议这样做
try:
file = open(file_path)
except OSError as e:
# do something
如果你用的Python版本为2.6+,那么用with
替代try…except…finally
可以进一步提升代码的易用性和简洁性。
with open(file_path) as file:
with
语句实现原理建立在上下文管理器之上。上下文管理器是一个实现 __enter__ 和 _exit\_ 方法的类。使用 with
语句确保在嵌套块的末尾调用 __exit__ 方法。这个概念类似于 try...finally
块的使用,但用with
语句不用关心如何做保护,只需要关心可能面临的异常即可。
善用"鸭子类型"
Python是一门动态语言,因此类型检查会失去Python的这种灵活性优势。相反,我们应该用鸭子类型类检测行为。如果你希望得到一个字符串,那么就用str()
将对象转换为字符串;如果你希望得到一个列表,那么就用list()
将可迭代对象转换成列表。
不要这样做
def foo(name):
if isinstance(name, str):
print(name.lower())
def bar(listing):
if isinstance(listing, list):
listing.extend((1, 2, 3))
return ", ".join(listing)
推荐这样做
def foo(name) :
print(str(name).lower())
def bar(listing) :
l = list(listing)
l.extend((1, 2, 3))
return ", ".join(l)
用上面的代码,函数foo()
支持传入一切对象;函数bar()
支持传入字符串、元组、集合、列表...等一切可迭代类型。更加符合DRY(Don't Repeat Yourself)原则。
不要在init之外初始化成员变量
很多其他语言(尤其是Java和PHP)转Python的开发者会习惯性地将成员变量写在类名下方,并赋予默认值。这样做在Python中虽然不会报错,但程序行为可能给你预期的不一样。这样定义的变量是类属性(静态变量)。
这意味着2大危害:
- 如果类属性发生改变,那么初始值也会变;
- 如果设置的初始值是一个可变对象,那么这个变量在实例间是共享的。
不要这样做(除非定义静态变量)
class Car(object):
color = "red"
wheels = [Wheel(), Wheel(), Wheel(), Wheel()]
推荐这样做
class Car(object):
def __init__(self):
self.color = "red"
self.wheels = [Wheel(), Wheel(), Wheel(), Wheel()]
总结
以上5条,只要大家在开发中能严格遵守,写出的代码无论是健壮性还是可维护性都会更行一层楼。