第2章 Python整洁之道
2.1 用断言加一层保险
断言用于程序内部自检,如声明一些代码中不可能出现的条件。如果触发了某个条件,即意味着程序中存在相应的bug。
Python的断言语句是一种调试辅助功能,不是用来处理运行时错误的机制。
不要使用断言来验证数据,断言是可以通过命令行参数(-O和-OO)或者环境变量(PYTHONOPTIMIZE)进行禁用的。
断言不要用括号,比如assert (1==2, ‘出错了‘),这种写法实际判断的是一个非空元组,这样断言永远都不会失败,也就不会触发。
正确的做法应该总是先对单元测试用例做一个快速的冒烟测试,保证断言能在错误发生时被触发。
2.2 巧妙地放置逗号
在列表、字典、集合的每一项后面都放置逗号,避免逗号缺失导致的bug。且每一项独占一行,可以在代码diff时方便比较。
2.3 上下文管理器和with语句
如果想把一个对象作为上下文管理器,就需要对其增加__enter__和__exit__方法。
with语法:
with 表达式 [as 变量]:
业务操作
其中:
表达式返回的是一个上下文管理器,即返回的对象需要有__enter__和__exit__方法。
而 [as 变量]这部分是可选的,注意:变量接收的不是表达式返回的对象而是表达式返回对象的__enter__方法返回的对象
表达式执行完之后就对调用返回对象的__enter__方法,业务操作执行完之后,离开with代码块就会执行表达式返回对象的__exit__方法
一个缩进示例:
class Indenter: def __init__(self): self.level = 0 def __enter__(self): self.level += 1 return self def __exit__(self, exc_type, exc_val, exc_tb): self.level -= 1 def print(self, text): print(‘ ‘ * self.level + text) with Indenter() as indent: indent.print(‘hi‘) with indent: indent.print(‘hello‘) with indent: indent.print(‘greeting‘) indent.print(‘bye...‘) """ 输出结果 hi hello greeting bye... """
还可是使用标准库中contextlib模块的装饰器contextmanager把一个函数变为上下文管理器
以下示例代码展示了两种方式的上下文管理器
from contextlib import contextmanager # class NoExit: # def __init__(self): # print(‘NoExit init‘) # # def write(self, content): # print(content) # # def __enter__(self): # print(‘NoExit enter‘) # # def __exit__(self, exc_type, exc_val, exc_tb): # print(‘NoExit exit‘) class ManagedFile: def __init__(self, name): self.name = name def __enter__(self): print(‘enter‘) self.file = open(self.name, ‘w‘) return self.file # return NoExit() def __exit__(self, exc_type, exc_val, exc_tb): print(‘exit‘) if self.file: self.file.close() # with ManagedFile(‘hello.text‘) as f: # f.write(‘hello‘) # f.write(‘hi‘) # with ManagedFile(‘hello.text‘) as f: # f.write(‘hello‘) # with f: # f.write(‘hello 2‘) # with f: # f.write(‘hello 3‘) @contextmanager def managed_file(name): try: f = open(name, ‘w‘) yield f finally: print(‘finally‘) f.close() with managed_file(‘hello_2.text‘) as f: f.write(‘hello2‘) f.write(‘hi2‘)
with语句关键要点:
一般用于管理资源的安全获取和释放。资源首先由with语句获取,并在执行离开with上下文时自动释放。
有效地使用with有助于避免资源泄露问题,让代码更加易于阅读
2.4 下划线、双下划线及其他
前置单下划线:_var:只是约定,告诉其他人:以单下划线开头的变量或方法只能在内部使用。只是一个警告标志:注意,这并不是这个类的公开接口,最好不要使用它。
后置单下划线:var_:只是约定,当变量名称与关键字冲突时,可用来关键字后面命名变量,比如:class_等
前置双下划线:__var:不是约定,解释器会重写双下划线开头的属性名称,以避免子类中的命名冲突
前后双下划线:__var__:
单下划线:_:
示例代码