文章目录
调用函数
Python本身就提供了很多函数直接调用,需要匹配正确的参数,如果输入的参数错误,会在错误提示中告诉你。
例如,绝对值函数,取最值函数,强制类型转换函数等。
>>> abs(-100)
100
>>> max(-1,2,3,4)
4
>>> int(12.56)
12
Python支持通过别名的方式调用函数:
>>> i=int
>>> i(12.56)
12
定义函数
格式
使用def语句定义,def后面接函数名,括号,括号中的参数以及冒号。例如,求绝对值函数:
def my_abs(x):
if x>=0:
return x
else:
return -x
注意:python中冒号的使用,不要少东西
与其他语句相同,执行到return 语句就返回,停止执行。没有return,则返回值为none。
导入函数
可以从py文件中导入函数来使用,例如
from input_output import my_abs;#此处的input_output是文件名,my_abs()是函数名
print(my_abs(-99))
占位符与类型检查
因为python中没有大括号的存在,可以使用pass作为占位符,构造空函数
def nop():#什么也不执行
pass
因为python定义变量时没有类型,因此没有参数检查。写一个完善的函数,就需要自己做参数检查。
def my_abs(x):
if not isinstance(x,(int, float)):
raise TypeError("not this type")#做一个参数类型检查,如果参数类型不对,提示错误信息
if x>=0:
return x
else:
return -x
关于多个返回值
Python函数可以return 多个值,格式是在return时使用,隔开。多个返回值会以tuple的形式返回。
def mult_return(x):
a=x+2
return x-1,x+1,a
print(mult_return(5))
运行结果:
(4, 6, 7)
函数的参数
位置参数
在正常情况下,python的函数参数是按,定义时的顺序传入:
例如:
def power(x,y):#计算x的y次方,依次读入x和y作为参数
sum=1
while y>0:
sum*=x
y-=1
return sum
print(power(2,3))
运行结果:
8
默认参数
可以在传入参数时设定一个参数的值,这样可以在调用时少传入一个参数
例如:
def power3(x,y=3):# y的默认值是3
sum=1
for i in range(y):
sum*=x
# print("第%d轮\n" %i)
return sum
print(power3(9,1))#带入两个参数,此时y的取值被覆盖
print(power3(9))#带入一个参数,y取默认值3
运行结果:
9
729
注意:在python中,函数中的参数并不是c++中的形参,而是一个变量。因此,如果讲函数参数设为可变的,那就会出问题。
例如:
def my_func(L=[]):
L.append('zcc')
return L
print(my_func())
print(my_func())
运行结果:
['zcc']
['zcc', 'zcc']
这是由于,作为参数的L被修改了。因此,默认参数必须指向不变对象
例如,将上面的程序进行修改,使L等于不变对象none
def my_func2(L=None):
if L is None:
L=[]
L.append('zcc')
return L
print(my_func2())
print(my_func2())
运行结果:
['zcc']
['zcc']
这样就保证每次输出的结果都一样了
注:不变对象:tuple,str,None
可变参数
用法类似于C++的数组作为函数参数,在传入参数数量不确定时使用。
情况1:
正常定义一个参数即可,传入时传入一个tuple或者list
def my_func3(L):
sum = 0 #注:sum是一个内置的变量名,最好不要用这个
for i in L:
sum += i
return sum
L=[1,2,3,5]
print(my_func3(L)) #将L作为参数传入
但是,此时想直接传入几个变量就不行了
例如:
print(my_func3(1,2,3,4))
就会报错,因为默认一个参数。
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-ZBlzcKfK-1631074952721)(C:\Users\26741\AppData\Roaming\Typora\typora-user-images\image-20210902103833246.png)]
因此需要先组合成list或者tuple
print(my_func3((1,2,3,4))
情况2
利用可变参数,相当于自动把传入的参数组合成tuple。免去自己组合的麻烦。这个方法有点像C语言中的取指针
def my_func4(*l1):
sum1 = 0
for i in l1:
sum1 += i
return sum1
L=(1,2,3,4)
print(my_func4(1,2,3,4))
print(my_func4(*L)) #在list或者tuple变量名前面加一个*即可
若想在可变参数中使用list或者tuple作为变量,可以直接传入。
运行结果:
10
10
关键字参数
关键词参数的变量类型必须是dict。可以是传入参数的时候作为一个key-value键值对传入,也可以就直接将一个dict变量集合传入。这种函数传递参数的方式,可以获得额外的变量值。
def my_func5(name, age, **kw):
print('name', name, 'age', age, 'other', kw)
my_func5('Bob', 12, city='Beijing', country='China')#此处的city='Beijing',就是以键值对形式传入
info={'city': 'tianjin', 'college': 'hebut'}
my_func5('zcc', 22, **info)#想直接将dict传入需要加**
输出结果
name Bob age 12 other {'city': 'Beijing', 'country': 'China'}
name zcc age 22 other {'city': 'tianjin', 'college': 'hebut'}
注:关键字函数传入的是一个拷贝,所以在针对关键字函数作出修改之后,不会对原来造成影响。
命名关键字参数
可以传入任意数量的参数,但是只接受想要的参数。原理就是中间用一个可变参数接受多余的变量。所有的命名关键字必须以键值对的形式插入,不能没有。缺一个都会报错
情况1:使用分隔符分割
def my_func6(name, age, *, city, school):
print('name:', name, 'age:', age, 'city', city, 'school', school)
my_func6('zcc', 22, city='baoding', school='hebut')
my_func6('zcc', 22, school='hebut', city='baoding')
这种情况下,* 后面被视为命名关键字,输入参数数量与函数定义必须数量一致。但,* 后面只要所有的命名都有,顺序可以不一致。
运行结果:
name: zcc age: 22 city baoding school hebut
name: zcc age: 22 city baoding school hebut
情况2:使用可变参数分割
def my_func7(name, age, *args, city, school):
print('name:', name, 'age:', age, 'city', city, 'school', school)
my_func7('zcc', 22, 1, 1, city='baoding', school='hebut')
这种情况下,中间多余的参数会被可变参数吃掉。但是可变参数后面不能再有多余的参数。
虽然python中可以定义多种函数,但是调用的时候必须遵照必选参数,默认参数,可变参数,命名关键字参数和关键字参数的顺序。
递归函数
调用自身的函数,通过栈实现。
def my_func7(n):
if(n == 1):
return 1
else:
return n * my_func7(n - 1)
print(my_func7(5))
由于栈的大小有限,因此没完没了的递归。会造成栈溢出。可以使用尾递归的方式解决。即:函数本身的返回语句不包括表达式,这样就不会占用多余的栈了。
def fact(n):
return fact1(n, 1)
def fact1(num , product):
if(num == 1):
return product #已经算到了最后一步
else:
return fact1(num-1, product * num) #乘以当前的数
print(fact(5))
不用让栈等着参数被计算,而是直接计算完。类似于循环。