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++的数组作为函数参数,在传入参数数量不确定时使用。
正常定义一个参数即可,传入时传入一个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))
利用可变参数,相当于自动把传入的参数组合成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'}
注:关键字函数传入的是一个拷贝,所以在针对关键字函数作出修改之后,不会对原来造成影响。
可以传入任意数量的参数,但是只接受想要的参数。原理就是中间用一个可变参数接受多余的变量。所有的命名关键字必须以键值对的形式插入,不能没有。缺一个都会报错
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
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))
不用让栈等着参数被计算,而是直接计算完。类似于循环。