一、Python函数的形式
def function_name (参数, ...) -> return value_type:
# 函数体
return value
# 看具体需求
# 如果没有return语句,函数执行完毕后也会返回结果
# 只是结果为None。return None可以简写为return
1. Python的返回值
在Python3中,提供了可以标注函数返回值的类型的功能,但Python是动态类型语言对返回值的类型标注不会像C++这种静态类型语言那样进行严格的类型检查和限制,所以我们可以认为返回值只是给程序员自己看着方便,在语法不会检查。
返回值标注的作用:
- 增强代码的可读性:标注返回值类型可以让其他开发者在阅读代码时更清楚地理解函数的预 期输出。
- 作为文档:有助于为使用该函数的其他开发者提供明确的信息,减少误解和错误使用。
- 辅助静态类型检查工具:虽然 Python 本身不强制检查,但结合一些第三方的静态类型检查 工具(如 mypy),可以在一定程度上进行类型检查,提前发现潜在 的类型错误。
【C++】
在C++中,函数的返回值类型是必须标注的,静态类型语言必须保证接收函数返回值的时候数据类型是匹配的
2. Python函数返回多个值
返回的是一个元组对象,在语法上,返回一个tuple可以省略括号,而多个变量可以同时接收一个tuple,按位置赋给对应的值,所以,Python的函数返回多值其实就是返回一个tuple,但写起来更方便;
而C++中返回多个值,可以采用输出型参数或者是返回一个类对象
def function_name (参数, ...):
return a, b ,c
如果函数的返回值我们只使用一部分,不关注其他的返回值,可以使用占位符 ‘ _ ’来进行占位
def func():
return 1, 2, 3
_, _, a = func()
print('a = %d' % a)
3. 空函数
def func():
pass
二、Python函数的参数
1. 位置参数:
与C++一致,实参的位置与形参的位置相匹配
2. 缺省参数:
与C++一致,形参有缺省参数,可以不传参也可以传参
设置缺省参数的规则:
- 参数在前,缺省参数在后
- 当函数有多个参数时,在传参时把变化大的参数放在前面,变化小的参数放在后面(变化小的参数可以作为缺省参数)
- 必须指向不可变对象
为什么默认参数在后?
当默认参数在前时,我们传入一个实参,就会发生疑问,这个实参是给缺省参数的?还是给参数的?因为可以一方面通过位置参数来,另一方面可以通过缺省参数来,所以就会产生二义性,为了防止此类事件的发生,规定缺省参数要在参数的后面。
缺省参数的坑:为什么要指向不可变对象?
Python函数缺省参数的 “ 坑 ” (与C++对比学习)-CSDN博客
3. 可变参数:
支持传入任意个参数,函数内部接收到的是一个元组tuple(在返回值和参数这里使用元组主要是保证传入或输出的对象的安全性,防止恶意篡改)
使用形式:
def func(*num):
s = 0
for i in num:
s += i
return s
ret = func(1, 2, 3, 4, 5, 6, 7, 8)
print(ret)
4. 显示命名参数
按照形参名字传参,无视位置,一般搭配缺省参数使用
使用形式:
def func(id_num, name='dd', age=20):
print('id:', id_num, '\nname:', name, '\nage:', age)
func(1, age=18)
5. 关键字参数
关键字参数允许我们传入任意个含有参数名的参数,这些关键字参数会在函数内部自动组装为一个dict。
使用形式:
def func(name, age, **kw):
print('name:', name, '\nage:', age, '\nothers:', kw)
func('dd', 20, city='上海', work='程序员')
简化版本:
**dic表示把该字典中的所有key:value用关键字参数传入函数的**kw中,需要注意的是kw获得的dict是dic的一份拷贝,对kw的改动不会影响函数外的dic
def func(name, age, **kw):
print('name:', name, '\nage:', age, '\nothers:', kw)
dic = {'city': '上海', 'work': '程序员'}
func('yy', 18, **dic)
6. 命名关键字参数
只可以传入命名关键字参数后的关键字参数
使用形式:
- 特殊分隔符 * 后面的参数被视为命名关键字参数
- 如果函数定义中有可变参数,后面跟着的命名关键字参数就不需要特殊分隔符*
- 命名关键字参数必须传入参数名
def fun(name, age, *, city, work):
print('name:', name, '\nage:', age, '\ncity:', city, '\nwork', work)
fun('wyd', 20, city='上海', work='程序员')
7. 各种参数可以组合使用
参数定义的顺序必须是:必选参数、默认参数、可变参数、命名关键字参数和关键字参数
三、递归函数
与C++一致,自己调用自己,但是要防止栈溢出,采用的方法是尾递归,保证每次函数调用只占用一个栈帧。
如计算n的阶乘:
采用递归的方式:
n值过大,则会导致栈空间溢出,因为下面这种是不断调用递归,会不断的压栈,从而导致栈空间不足
def fact(n):
if n == 1:
return n
return n * fact(n-1)
采用尾递归的方式:
每次只用一个栈帧,尾递归的好处就是最外层的函数调用完自身就会销毁函数栈帧,从而保证每次只使用一个栈帧,遗憾的是,大多数编程语言没有针对尾递归做优化,Python解释器也没有做优化,所以,即使把上面的
fact(n)
函数改成尾递归方式,也会导致栈溢出。
def fact_operator(n, s):
if n == 1:
return s
return fact_operator(n - 1, n * s)
def fact(n):
return fact_operator(n, 1)