定义和调用函数 Python 中使用def
语句创建函数,其一般的格式如下所示:
1 2 def name (arg1, arg2, ...,argN ): statements
下面这段代码定义 了一个简单函数。
1 2 3 def repeator (s, n ): result = s * n print (result)
这段代码仅仅是对函数的定义,并没有调用执行。这条定义语句运行后会新建一个名为repeator
的变量名,其类型为function
,即函数。
1 2 3 4 5 def repeator (s, n ): result = s * n print (result)print (type (repeator))
与内置函数一样,定义完函数后,可以通过函数名调用 执行。
1 2 3 4 5 def repeator (s, n ): result = s * n print (result) repeator('嗷' , 3 )
在很多情况下,函数需要将计算的结果返回到调用处。在这类函数的函数体中,通常包含一条return
语句:
1 2 3 def name (arg1, arg2, ...,argN ): statements return value
在创建函数时, 没有在函数体中添加return
语句,Python 也会默默地在函数体最后添加一条return None
。
1 2 3 4 5 6 7 def repeator (s, n ): result = s * n print (result) value = repeator('嗷' , 3 )print (value)
函数如果以返回值来输出:
1 2 3 4 5 def repeator (s, n ): result = s * n return resultprint (repeator('嗷' , 3 ))
在 Python 中, 还允许在函数中返回多个值。 只需将返回值以逗号隔开, 放在return
关键字后面即可。
1 2 3 4 5 6 def calculator (m, n ): return m+n, m-n, m*n, m/n i, j = 2 , 4 r1, r2, r3, r4 = calculator(i, j)print (f'{i} 和 {j} 的加减乘除运算结果是:{r1} ,{r2} ,{r3} ,{r4} ' )
在这里总结一下函数调用的四个步骤:
程序执行到函数调用时,在调用处暂停,等待函数执行完毕; 将实参赋值给函数的形参; 执行函数体中的语句; 调用结束后,回到调用前暂停处继续执行,如果函数体中执行了return
语句, return
关键字后的值会返回到暂停处,供程序使用,否则函数返回None
值。 函数参数 参数传递 参数的传递过程,实际上是一个赋值的过程。在调用函数时,调用者的实际参数自动赋值给函数的形式参数变量。
1 2 3 4 def avg (m, n ): return (m + n) /2 print (avg(5 , 2 ))
不可变和可变类型参数 目前我们所学习的不可变类型包括:整型、浮点型、字符串和元组,可变类型有:列表、字典和集合等。这些都可以作为参数的类型。但参数在函数中使用时,这两种类型的表现有所不同。
下面的代码调用时,传递的是不可变类型的参数:
1 2 3 4 5 6 7 8 def priceChanger (p ): p = p + 10 print ('改变后的价格:{:.2f}' .format (p)) price = 10.8 priceChanger(price)print (price)
在使用可变参数时,函数体中可以改变参数的元素:
1 2 3 4 5 6 7 8 def contentChanger (name_list ): name_list[0 ], name_list[1 ] = name_list[1 ], name_list[0 ] print ('函数中的 name_list:' , name_list) language_name = ['C' , 'Python' ] contentChanger(language_name)print ('调用函数后的 language_name:' , language_name)
因此,在使用可变类型参数时需要特别注意,如果在函数中修改了参数的元素,这种修改会影响调用者的变量。 如果想消除这种影响,可以使用列表copy
方法或者使用分片操作创建新列表。
位置参数 位置参数是调用函数为形参赋值的一种默认方式。实参与形参按照从左到右的位置顺序依次赋值。
1 2 3 4 def myMinus (num1, num2 ): return num1 - num2print (myMinus(5 , 2 ))
赋值顺序改变将得到不同的结果。
1 2 3 4 def myMinus (num1, num2 ): return num1 - num2print (myMinus(2 , 5 ))
关键字参数 为了避免位置参数赋值带来的混乱,Python 允许调用函数时通过关键字参数的形式指定形参与实参的对应关系。 调用者使用name=value
的形式来指定函数中的哪个形参接受某个值:
1 2 3 4 5 6 def myMinus (num1, num2 ): return num1 - num2print (myMinus(num1=5 , num2=2 ))print (myMinus(num2=2 , num1=5 ))
指定默认参数值 在函数定义时,可以为参数指定值。这样当函数调用者没有提供对应参数值时,就可以使用指定的默认值。 指定默认参数值在 Python 的函数中广泛存在。例如,打印函数print
,在查看其帮助时,其函数的部分描述如下:
1 2 3 4 5 6 7 8 9 print(...) print(value, ..., sep=' ', end='\n', file=sys.stdout, flush=False) Prints the values to a stream, or to sys.stdout by default. Optional keyword arguments: file: a file-like object (stream); defaults to the current sys.stdout. sep: string inserted between values, default a space. end: string appended after the last value, default a newline. flush: whether to forcibly flush the stream.
可以看到,print
函数的sep
、end
、file
和flush
参数都指定了默认值。
1 2 print ('C' , 'C++' , 'Java' , 'Python' )
如果调用时指定了sep
参数的值,则会使用该值来连接每个打印的值。
1 2 print ('C' , 'C++' , 'Java' , 'Python' , sep='_' )
在定义函数时, 为形参指定默认值, 就可以让该形参在调用时变为可选:
1 2 3 4 5 6 def myMod (x, y=2 ): return x % yprint (myMod(13 ,4 ))print (myMod(13 ))
任意数量参数 Python 允许在定义函数时使用单星号*
来收集位置参数,双星号**
收集关键字参数。
单星号*收集位置参数 单个星号将一组可变数量的位置参数组合成参数值的元组。在函数内部可以通过访问元组中的每个元素来使用参数。
1 2 3 4 5 6 def m_value (*values ): max_value = max (values) min_value = min (values) print (f'最大值: {max_value} , 最小值: {min_value} ' ) m_value(8 , 6 , 7 , 4 , 3 , 9 )
双星号**收集关键字参数 针对形参的关键字参数赋值形式, 利用 Python 定义函数时, 在形参前面加上双星号**
来定义收集关键字参数的形参。此时形参是字典类型。
1 2 3 4 5 6 7 8 9 10 def f (**info ): if 'name' not in info.keys(): print ('必须拥有名称信息。' ) else : print (info['name' ] + '的诞生年份:' + info.get('time' , '不详' )) f(name = 'C' , time = '1972' ) f(name = 'Python' )
解包参数 在调用函数时,实参也可以使用*
和**
语法。此时不是收集参数,正好相反, 实参前加上*
或**
执行的是参数解包。 通常来说, 在列表、元组等类型的实参值前加上*
, 将这些类型的元素解包成位置参数的形式;在字典类型的实参值前加上**
,将字典的元组解包成关键字参数的形式。
当调用者的数据存储在列表中时, 可以通过在列表前加上*
对列表解包来实现位置参数形式的调用。
当调用者的数据存储在字典中时, 可以通过在字典前加上**
对字典解包来实现关键字参数形式的调用。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 def f (name, time='不详' ): if name and len (name) > 0 : print (name + '的诞生年份:' + str (time)) else : print ('必须拥有名称信息。' ) info1 = ['C' , '1972' ] f(*info1) info2 = {'name' : 'Python' , 'time' : '1989' } f(**info2)