Python函数
Python不但能非常灵活地定义函数,而且本身内置了很多有用的函数,可以直接调用。
一、定义函数
在Python中,定义一个函数要使用def语句,依次写出函数名、括号、括号中的参数和冒号:,然后,在缩进块中编写函数体,函数的返回值用return语句返回。
def my_abs(x):
if x >= 0:
return x
else:
return -x
二、导入外部函数
from 外部文件名 import 外部函数名
三、空函数
空函数:什么也不做的函数,pass可以用来作为占位符,比如现在还没想好怎么写函数的代码,就可以先放一个pass,让代码能运行起来。
def nop():
pass
缺少了pass,代码运行就会有语法错误。
if age >= 18:
pass
四、求绝对值的abs函数
abs(100)
五、求最大值的函数max
max()可以接收任意多个参数,并返回最大的那个
max(2, 3, 1, -5)
六、数据类型转换函数
比如int()函数可以把其他数据类型转换为整数
int('123')
float('12.34')
str(1.23)
bool(1)
七、把一个整数转换成十六进制表示的字符串
hex()
八、给函数起别名
函数名其实就是指向一个函数对象的引用,完全可以把函数名赋给一个变量,相当于给这个函数起了一个“别名”。
a = abs # 变量a指向abs函数
a(-1) # 所以也可以通过a调用abs函数
九、数据类型检查函数
isinstance()
十、函数返回“多个值”
其实这只是一种假象,Python函数返回的仍然是单一值
返回值是一个tuple!但是,在语法上,返回一个tuple可以省略括号,而多个变量可以同时接收一个tuple,按位置赋给对应的值,所以,Python的函数返回多值其实就是返回一个tuple,但写起来更方便。
十一、函数参数
(1)位置参数
def power(x):
return x * x
对于power(x)函数,参数x就是一个位置参数。
(2)默认参数
def power(x, n=2):
s = 1
while n > 0:
n = n - 1
s = s * x
return s
这里的n=2就是默认参数
默认参数的注意事项:
(Ⅰ)必选参数在前,默认参数在后,否则Python的解释器会报错;
(Ⅱ)当函数有多个参数时,把变化大的参数放前面,变化小的参数放后面。变化小的参数就可以作为默认参数;
(Ⅲ)当不按顺序提供部分默认参数时,需要把参数名写上;
(Ⅳ)定义默认参数要牢记一点:默认参数必须指向不变对象!
(3)可变参数
可变参数就是传入的参数个数是可变的,可以是1个、2个到任意个,还可以是0个。
在参数前面加一个*
号,就可以定义可变参数
def calc(*numbers):
sum = 0
for n in numbers:
sum = sum + n * n
return sum
特别的,如果已经有一个list或者tuple,要调用一个可变参数怎么办?
nums = [1, 2, 3]
calc(*nums)
*nums
表示把nums
这个list的所有元素作为可变参数传进去。这种写法相当有用,而且很常见。
(4)关键字参数
**参数名
关键字参数允许你传入0个或任意个含参数名的参数,这些关键字参数在函数内部自动组装为一个dict。
def person(name, age, **kw):
print('name:', name, 'age:', age, 'other:', kw)
传入dict:**dict名
(5)命名关键字函数
def person(name, age, *, city, job):
print(name, age, city, job)
和关键字参数**kw不同,命名关键字参数需要一个特殊分隔符,后面的参数被视为命名关键字参数。
如果函数定义中已经有了一个可变参数,后面跟着的命名关键字参数就不再需要一个特殊分隔符*了:
def person(name, age, *args, city, job):
print(name, age, args, city, job)
命名关键字参数可以有缺省值,从而简化调用:
def person(name, age, *, city='Beijing', job):
print(name, age, city, job)
(6)参数组合
在Python中定义函数,可以用必选参数、默认参数、可变参数、关键字参数和命名关键字参数,这5种参数都可以组合使用。但是请注意,参数定义的顺序必须是:必选参数、默认参数、可变参数、命名关键字参数和关键字参数。
def f1(a, b, c=0, *args, **kw):
print('a =', a, 'b =', b, 'c =', c, 'args =', args, 'kw =', kw)
def f2(a, b, c=0, *, d, **kw):
print('a =', a, 'b =', b, 'c =', c, 'd =', d, 'kw =', kw)
(7)对于任意函数,都可以通过类似func(*args, **kw)的形式调用它,无论它的参数是如何定义的。
十二、递归函数
在函数内部,可以调用其他函数。如果一个函数在内部调用自身本身,这个函数就是递归函数。
def fact(n):
if n==1:
return 1
return n * fact(n - 1)
使用递归函数需要注意防止栈溢出。
解决递归调用栈溢出的方法是通过尾递归优化,事实上尾递归和循环的效果是一样的,所以,把循环看成是一种特殊的尾递归函数也是可以的。
尾递归是指,在函数返回的时候,调用自身本身,并且,return语句不能包含表达式。这样,编译器或者解释器就可以把尾递归做优化,使递归本身无论调用多少次,都只占用一个栈帧,不会出现栈溢出的情况。
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)
尾递归调用时,如果做了优化,栈不会增长,因此,无论多少次调用也不会导致栈溢出。
遗憾的是,大多数编程语言没有针对尾递归做优化,Python解释器也没有做优化,所以,即使把上面的fact(n)函数改成尾递归方式,也会导致栈溢出。
十三、总结
(1)定义可变参数和关键字参数的语法:
*args是可变参数,args接收的是一个tuple;
**kw是关键字参数,kw接收的是一个dict。
(2)调用函数时如何传入可变参数和关键字参数的语法:
可变参数既可以直接传入:func(1, 2, 3),又可以先组装list或tuple,再通过args传入:func((1, 2, 3));
关键字参数既可以直接传入:func(a=1, b=2),又可以先组装dict,再通过kw传入:func()。