二、函数
14 尽量用异常来表示特殊情况,而不要返回None
- None 和0及空字符之类的值,都评估为False,容易犯错
15 如何在闭包里使用外围作用域中的变量
这一条有点搞脑子
- 引用变量时,会从里到外遍历各个作用域。
- 变量赋值时,当前作用域内没有这个变量,会新定义这个变量,而不会向外遍历作用域。即,使用默认方式对闭包内的变量赋值,不会影响外围作用域中的同名变量。
- Python 3 ,在闭包内用nonlocal修饰某个名称,即可实现修改外围作用域中的同名变量;Python 2 ,可以使用可变值(例如,包含单个元素的列表)来实现。
- 尽量不要使用 nonlocal语句。
16 用生成器改写直接返回列表的函数
生成器是用yield表达式的函数。
例如,确定字符串的首字符索引
from itertools import islice
def index_word_iter(text):
if text:
yield 0
for index, letter in enumerate(text):
if letter == ' ':
yield index + 1
address = 'Four score and...'
result1 = list(index_word_iter(address))
it = index_word_iter(address)
result2 = list(islice(it, 0, 1))
print result1
print result2
>>>[0, 5, 11]
>>>[0]
17 在参数上面迭代时,要多加小心
虽但厉。好的,我会小心的。
18 数量可变的位置参数 *args
- 在def语句中使用*args,即可令函数接受数量可变的位置参数。
- 调用函数时,可以采用*操作符,把序列中的元素当成位置参数,传给该函数。
def log(message,*values):
pass
19 用关键字参数来表达可选的行为
- 函数参数的指定可按位置或关键字
- 关键字参数能够阐明每个参数的意图
- 给函数添加新的行为时,可以使用带默认值的关键字参数,以便与原有的函数调用代码保持兼容
- 可选的关键字参数,总是应该以关键字形式来指定
函数调用时,位置参数必须出现在关键字参数之前,每个参数只能指定一次。
20 用None和文档字符串来描述具有动态默认值的参数
- 参数的默认值,只会在程序加载模块并读到本函数的定义时评估一次。对于{}或[]等动态的值,会导致奇怪的行为。
- 对于以动态值作为实际默认值的关键字参数,应把默认值写为None,并在函数的文档字符串里面描述该默认值所对应的实际行为。
def decode(data,default=None):
```Load JSON data from a string.
Args:
data:
default:...#描述
```
if default is None:
default = {}
pass
21 用只能以关键字形式指定的参数来确保代码明晰
Python 3:参数列表里的 * 好标志这位置参数就此终结,之后的参数,只能以关键字形式来指定
def safe_division(number,divisor,*,io=False,iz=False):
pass
safe_division(1,0,True,False) #错误
safe_division(1,0) #正确,后面两个采用缺省值
safe_division(1,0,iz=True) #正确
Python 2:没有明确地语法来定义只能以关键字形式指定的参数。不过,可以在参数列表中使用**
操作符,并令函数在遇到无效的调用时抛出TypeErrors。 操作符**
是用来接受任意数量的关键字参数,即使某些关键字没有定义在函数中,它也能接受。
def sd(n,d,**ks):
io=ks.pop('io',False)
iz=ks.pop('iz',False)
if ks:
raise TypeError('Unexpected **ks:%r' %ks)
sd(1,0)
sd(1,0,iz=True)
sd(1,0,False) #会产生TypeError