19. 不要把函数返回的多个值拆分到三个以上变量中

返回多个,即超过三个的时候,可以用星号变量来捕获其余的多个变量。也可以定义一个轻便的类或namedtuple来整合这些需要返回的变量

20. 遇到意外情况要跑出异常而不是返回None

在条件表达式里 None,0,’’都表示False。

21. 了解如何在闭包里使用外围作用域中的变量

22. 用数量可变的位置参数给函数设计清晰的参数列表

*b可接受可变数量的参数值,会存在名为b的元组中。可以是函数编写更加简洁,适合参数量不是特别多的情形,使用这种方法也会存在一些问题,比如出现bug时调试困难,不要传入迭代器。
image.png

23. 用关键字参数来表示可选行为

所谓关键词参数就是函数中传入参数时加上参数名,如下面,这样可以让人更易读懂

  1. def A(a, b=1):
  2. print(a, b)
  3. A(a=1, b=2)

可选行为即为指定了默认值的参数,如上面的b参数。A(1, b=2)
**kwargs,相比于22中的星号,两个星号用于接收任意参数
image.png

24. 用None和docstring来描述默认值会变的参数

函数参数的默认值会在系统加载函数的时候就固定,因此不能写成以下形式,这样的b他并不会随时间而变化。也不要把默认值设置为[],{}等

  1. from datetime import datetime
  2. def A(a, b=datetime.now())
  1. 对于可选参数我们一般采用默认值,而如果希望这个默认值是动态的或者说是会变的,那么就得在函数内部判断
  1. def A(a, b=None):
  2. if None:
  3. pass

25. 用只能以关键字指定和只能按位置传入的参数来设计清晰的参数列表

对于一些比较复杂的函数,对于可选参数,我们可以使其必须要指定参数名赋值,这样更易懂,对于下式中的函数A,如果要修改c,那么在调用时必须为A(1,2,c=2),即只能以关键字指定

  1. def A(a, b, *, c=1)
  1. python3.8之后的新特性可以使得函数中的参数只能按位置传入,而不能切换位置,也不能指定参数名。'/'前面的a,b参数传值时必须为A(1, 2),不能指定为A(a=1, b=2)
  1. def A(a, b, /, c)

26. 用functools.wraps定义装饰器

wraps装饰器可以保留被装饰函数中的元数据,可以将重要的元数据从内部函数复制到外部函数。如果不适用wraps装饰器,则无法对fibo函数进行序列化,因为fibo其实对应的是mywraps函数,同时使用help(fibo)得到的也是mywraps的信息。

  1. from functools import wraps
  2. def myfunc(func):
  3. @wraps(func)
  4. def mywraps(n):
  5. result = func(n)
  6. print(n, result)
  7. return result
  8. return mywraps
  9. @myfunc
  10. def fibo(n):
  11. """
  12. fibo n
  13. """
  14. if n <= 2:
  15. return 1
  16. return fibo(n - 1) + fibo(n - 2)
  17. help(fibo)