python cookbook 学习笔记 第七章 函数(5) 定义有默认参数的函数

  • 定义有默认参数的函数
  • 问题:
  • 想定义一个函数或者方法,他的参数是一个或多个可选的并且有一个默认值。
  • 解决方案:
  • 定义一个有可选参数的函数非常简单,直接在函数定义中给参数指定一个默然值,并放到参数列表最后就可以了。比如:
#def spam(a, b= 42):
#    print(a, b)

#spam(1) # 1 42
#spam(1, 2) # 1 2
  • 如果默认参数是一个可修改的容器,比如一个列表、集合或者字典,可以使用None作为默认值,就像下面这样:
def  spam(a, b= None):
    if b is None:
        b = []
        ...
  • 如果并不想提供一个默认值,而是仅仅测试下某个默认参数是不是有传递进来,可以像下面这样写:
_no_value = object()

def spam(a, b= _no_value):
    if b is _no_value:
        print("No b Value supplied")
  • 我们来测试下这个函数
spam(1) # No b Value supplied
spam(1, None)
  • 仔细观察,传递一个None和不传值是有差别的。

  • 讨论: 默认参数的值仅仅在函数定义的时候赋值一次。

x = 42
def spam(a, b =x):
    print(a, b)

spam(1) # 1 42

x = 32
spam(1) # 1 42
  • 当x的值改变的时候,默认参数并没有影响,因为在函数定义的时候就已经确认它的默认值了。

  • 其次,默认参数的值应该是不可变得对象,比如None, True, False, 数字或者字符串。不 要像下面这样写代码:


def spam(a, b= []):  # NO!!
    ...
  • 如果这么做了,在默认值在其他地方被修改后,会遇到各种麻烦。这些修改会影响到下次调用这个函数时的默认值。比如:
def spam(a, b=[]):
    print(b)
    return b

x = spam(1) # []

x.append(99)
x.append("yow!")

spam(1) # [99, 'yow!']
  • 这种结果不是你想要的,为了避免这种情况的发生,最好将默认值设为None,然后在函数里面检查它。在测试None值时,使用is操作符石很重要的,也是这种方案的关键点,有时候大家会犯下面这样的错误:
def spam(a, b= None):
    if not b:
        b = []
        ...
  • 这么写的问题问题在于尽管None值确实被当做False, 但是还有其他的对象(比如长度为0的字符串、列表、元组、字典等)都会被当做False。 因此,上面的代码会误将一些其他输入也当成没有 输入,比如:
spam(1)
x = []
spam(1, x)
spam(1, 0)
spam(1, "")
  • 最后一个问题比较微妙,那就是一个函数需要测试某个可选参数是否被使用者传递进来。这个时候需要小心的是你不能用某个默认值比如 None, 0 或者False值来测试用户提供的值(因为这些值都是合法的值,是可能被用户传递进来的)。因此,需要其他的解决方案。
  • 为了解决这个问题,可以创建一个独一无二的私有对象实例,就像上面的_no_value变量那样。在函数里面,你可以通过检查被传递参数值是否跟这个实例一样来判断。这里的思路是用户不可能传递 _no_value 实例作为输入。因此,这里通过检查这个值就能确定某个参数是否被传递进来了。
  • 这里对object()的使用看上去有点不太常见。object是Python中所有类的基类。可以创建object类的实例,但是,这些实例没有什么实际的用处,因此它并没有任何有用的方法,也没有任何实例数据,(因为它没有任何的实例字典,设置不能设置任何属性值)。唯一能做的久是测试同一性。

你可能感兴趣的:(Python,cookbook,学习笔记,第七章)