调用函数
数据类型转换
int('123')``float('12.34')``str(123)``bool(1)
定义函数
空函数
如果想定义一个什么事也不做的空函数,可以用
pass
语句参数检查
自己写函数时,如果要检查参数类型:
def my_abs(x):
if not isinstance(x, (int, float)):
raise TypeError('bad operand type')
pass
返回多个值
Python函数返回的其实是个
tuple
,因为返回一个tuple
可以省略括号,而多个变量可以同时接收一个tuple
函数执行完毕也没有
return
语句时,自动return None
函数的参数
默认参数
必选参数在前,默认参数在后。变化大的参数放在前面,变化小的参数放在后面
💡 定义默认参数要牢记一点:默认参数必须指向不变对象
def add_end(L=[]):
L.append('END')
return L
add_end() #['END']
add_end() #['END', 'END']
#默认参数L也是一个变量,它指向对象[]
可变参数
def calc(*args)
在参数前面加一个*
即定义为可变参数。如果num
是一个list,那么*num
表示将这个list中的所有元素作为可变参数传入函数中,在函数调用时自动组装为一个tuple关键字参数
**kw
关键字参数允许传入0个或任意个含参数名的参数,这些关键字参数在函数内部自动组装为一个dictdef person(name, age, **kw):
print('name', name, 'age', age, 'other', kw)
extra = {'city':'Beijing', 'job':'Engineer'}
person('Jack', 24, **extra)
#注意kw获得的dict是extra的一份拷贝,对kw的改动不会影响到函数外的extra
命名关键字参数
命名关键字参数是为了限制调用者可以传入的参数名,同时可以提供默认值
def person(name, age, *, city, job):
命名关键字参数需要一个特殊分隔符*
,*
后面的参数被视为命名关键字参数。否则将视为位置参数命名关键字参数必须传入参数名,如果没有传入参数名,调用将报错
参数组合
参数定义的顺序必须是:必选参数、默认参数、可变参数、命名关键字参数和关键字参数
递归函数
函数调用时通过栈(stack)这种数据结构实现的,每当进入一个函数调用,栈就会加一层栈帧,每当函数返回,栈就会减一层栈帧。由于栈的大小不是无限的,所以递归调用次数过多会导致栈溢出
- 解决递归调用栈溢出的方法是通过尾递归优化,事实上尾递归和循环的效果是一样的,可以把循环看成是一种特殊的尾递归函数 ```python def fact(n): return fact_iter(n, 1)
def fact_iter(num, product): if num == 1: return product return fact_iter(num - 1, num * product) ```
return fact_iter(num - 1, num * product)
仅返回递归函数本身,num - 1
和num * product
在函数调用前就会被计算,不影响函数调用- 💡 Python标准的解释器没有针对尾递归做优化,任何递归函数都存在栈溢出的问题