本节介绍如何将语句组合成函数。函数执行特定的操作并返回一个值,你可以调用它。
一、自定义函数
1、def语句
使用def语句表示定义函数。
def hello(name): return 'Hello, ' + name + '!'
可以直接调用这个函数:
>>> print(hello('world')) Hello, world!
return语句用于从函数返回值。如果没有return语句,默认返回None。
2、函数参数
在def语句中,位于函数名后面的变量通常称为形参,如示例中的name。调用函数时提供的值称为实参,如示例中的'world'。
参数存储在局部作用域内,在函数内部给参数赋值对外部没任何影响。
name = 'world' def hello(name): name = 'python' print('inside:', name) hello(name) print('outside:', name)
inside: python
outside: world
二、参数魔法
1、位置参数
def hello(title, name): print('hello,', title, name) hello('2020', 'world') hello('world', '2020') hello, 2020 world hello, world 2020
上述使用的参数title,name都是位置参数,因为他们的调用位置至关重要。
2、关键字参数和默认值
参数的排列顺序可能难以记住,尤其参数很多时,这时候可以指定参数的名称。
>>> hello(title='2020', name='world') hello, 2020 world
像这样使用名称指定的参数称为关键字参数,便于非常鲜明的指出各个参数的作用。
虽然这样的输入量多一些,但每个参数的作用清晰明了,并且参数的顺序错了也没关系。
关键字参数最大的优点在于,可以指定参数默认值。
def hello(title='2020', name='world'): print('Hello,', title, name)
给参数指定默认值后,调用函数时可不提供它。可以根据需要,提供部分参数值或者全部参数值。
>>> hello() Hello, 2020 world >>> hello('2019') Hello, 2019 world >>> hello('2019', 'Java') Hello, 2019 Java
3、收集参数
有时候,允许用户提供任意数量的参数很有用。
我们可以用带星号的参数将余下的值都放在一个元组中。
>>> def print_params(title, *params): ... print(title) ... print(params) ... >>> print_params('Params:', 1, 2, 3) Params: (1, 2, 3)
如果没有可供收集的参数,params将是一个空元组。
带星号的关键字参数也可放在中间位置,但这时候需要使用名称来指定后续参数,否则就会发生异常。
>>> def in_the_middle(x, *y, z): ... print(x) ... print(y) ... print(z) ... >>> in_the_middle(1, 2, 3, 4, 5, 6, 7) Traceback (most recent call last): File "<stdin>", line 1, in <module> TypeError: in_the_middle() missing 1 required keyword-only argument: 'z' >>> >>> in_the_middle(1, 2, 3, 4, 5, 6, z=7) 1 (2, 3, 4, 5, 6) 7
4、收集关键字参数
星号不会收集关键字参数。要收集关键字参数,可使用两个星号。
这样会得到一个字典。
>>> def print_params(**params): ... print(params) ... >>> print_params(x=1, y=2, z=3) {'x': 1, 'y': 2, 'z': 3}
5、分配参数
前面介绍了如何将参数收集到元组和字典中,但用同样的两个运算符(*和**)也可执行相反的操作,及分配参数。
>>> def add(x, y): ... print(x) ... print(y) ... return x + y ... >>> >>> params = (1 ,2) >>> add(*params) 1 2 3
使用运算符**,可将字典中的值分配给关键字参数。
>>> def hello(greeting='Hello', name='world'): ... print('{}, {}!'.format(greeting, name)) ... >>> params = {'name': 'Mike', 'greeting': 'Hello'} >>> hello(**params) Hello, Mike!
使用这些拆分运算符来传递参数很有用,尤其在调用父类的构造函数时特别有用。
def foo(x, y, z, m=0, n=0): print(x, y, z, m, n) def call_foo(*args, **kwds): print('Calling foo!') foo(*args, **kwds)