python的函数又称为方法,就是将一堆代码进行重用的机制。函数就是一段代码,这段代码专门为了某种目的而设计,可以有输入的值也可以无输入的值,可以有返回结果,也可以没有返回结果。我们通过调用它,来执行特定的事情。
函数的定义:
函数
def MethodName([参数]):
代码块
[return表达式]
MethodName为函数名 可以随意定义 但自己一定要清楚函数作用
参数有无均可 但无参数无法完成某些函数的定义
有无返回值均可 默认返回值是None
函数的调用机制与栈的调用机制相同,先进后出,后进先出。函数有return语句就有返回值,此时需要一个变量来接受函数返回的值,然后用print语句输出结果。无return语句就没有返回值,此时直接调用语句不需要用变量接受就会有输出结果
1.有无返回值
下面是一个无返回值的函数,money是传入的参数
def Buy(money):
if money>10:
print("帝豪")
else:
print("红塔山")
调用函数Buy传入参数7
Buy(7)
语句执行的结果如下:
红塔山
若你用一个参数来接受函数,然后输出结果,会发现输出的结果是None
下面是一个有返回值的函数:
def Buy(money):
if money>10:
return ("帝豪")
else:
return("红塔山")
a=Buy(7)
print(a)#或者print(Buy(7))二者结果相同
运行结果是:
红塔山
若你不用变量接收,直接调用参数,则运行后没有任何结果
2 .参数
参数分为两种,分别是实际参数和形式参数
上面已经说到函数能够传入参数也能够不传入参数,不传入参数很好理解,然而传入参数时传入形参(形式参数)实参(实际参数)又有什么不同呢?
形式参数是指在编写方法的时候,预定义的参数,实际参数是指在实际调用的时候,传入方法的参数。
下面我们来看一个函数:
def CircleArea(r):
return 3.14*r*r
L=5
Area=CircleArea(L)
print(Area)
运行结果是:
78.5
在这个函数中r就是形式参数,L就是实际参数,在调用方法时我们将L的值传递给r,然后运行输出结果,传递参数的过程称为传参。
3.形式参数
上面已经简单的介绍了形式参数和实际参数,形式参数还可分为可选参数、命名参数、可变元组参数、可变字典参数
(1) 可选参数
可选参数也可称为默认参数,是给方法的特定参数指定默认值,在调用方法时可以省略掉这些参数。需要注意的是可选参数必须位于所有的必选参数之后;可选参数必须指定一个默认的值,且默认值必须是个常量表达式,不能是变量;可选参数的后面都是可选参数,若要为可选参数传递新的值,注意数据类型。
(2) 命名参数
命名参数,也可叫关键字参数。对于关键字参数,函数调用使用关键字参数来确定传入的参数值,另外命名参数允许函数调用时参数的顺序和声明不一致。
关键字参数和函数调用关系紧密,函数调用使用关键字参数来确定传入的参数值
def MehtodB(a,b,*,c="李龙龙",d="李小龙"):
print("a:",a)
print("b:",b)
print("c:",c)
print("d:",d)
MehtodB(5,6,d=6,c=16)
a: 5
b: 6
c: 16
d: 6
(3)可变元组参数
在python函数中,还可以定义可变参数。顾名思义,可变参数就是传入的参数的个数是可变的,可以是任意个,具有很好的灵活性。可变元组参数将参数组装成了一个tuple(元组)
def MethodC(b,*a):
print(a)
print(type(a))
print(b)
for i in a:
print(i,end="\t")
MethodC(1,58,3,87,5,38,8,2,8,5)
运行结果:
(58, 3, 87, 5, 38, 8, 2, 8, 5)
<class 'tuple'>
1
58 3 87 5 38 8 2 8 5
(4) 可变字典参数
可变字典参数允许传入任意个参数,传入的参数必须是键值对的形式,这些传入的参数最后以键值对的形式组装成了字典。
def num(x,y,**z):
print(x+y)
print(type(z))
print(z)
num(1,2,a=2,b=3)
运行结果如下:
3
<class 'dict'>
{'a': 2, 'b': 3}
4. 全局变量和局部变量
全局变量和局部变量的本质区别就是在于作用域。全局变量在整个py文件中都可以访问;局部变量是在某个函数中声明的,只能在该函数中调用它,函数外无法被调用,可以用global关键字将局部变量修改成全局变量。
def fun():
num1=2
print("函数内修改num1后 num1=",num1)
num1=1
print("初始num1:",num1)
fun()
print("函数运行后num1:",num1)
由于num1是局部变量,对函数外部没有影响,所以运行结果是:
初始num1: 1
函数内修改num1后 num1= 2
函数运行后num1: 1
将num1声明为去盐焗变量后,num1的值发生了改变,运行结果:
def fun():
global num1
num1=2
print("函数内修改num1后 num1=",num1)
num1=1
print("初始num1:",num1)
fun()
print("函数运行后num1:",num1)
运行结果:
初始num1: 1
函数内修改num1后 num1= 2
函数运行后num1: 2
5.可变类型和不可变类型
不可变类型:整数、浮点数、bool、字符串、元组。不可变类型传参时,只是将值传递到方法中,不影响外部变量
def MethodA(a):
a+=1
a=3
MethodA(a)
print(a)
运行结果是:
3
可以看到将a传入到MethodA函数中后,a的值并未发生改变,这是因为a是不可变类型。
可变类型:列表、字典、set集合、类、对象
def MethodB(a):
a[0]=-1
a=[7,3,1]
MethodB(a)
print(a)
运行的结果是:
[-1, 3, 1]
可以看到列表a的值发生了变化。
6.匿名函数
匿名函数是指无需定义函数名的函数或子程序
语法格式:lambda 参数:表达式
lambda语句中,开头先写关键字lambda,冒号前是参数,可以有多个,用逗号隔开;冒号右边的时表达式,注意只有一个表达式,由于lambda返回的是一个函数对象,所以要用一个对象去接收它
匿名函数可以省去函数定义的过程让代码更精简,对于一些抽象的、不会被别的地方用到的函数,有时候如何起名字也是个难题,使用匿名函数,不用再考虑命名的问题
nums=[12,45,3,65,23,21]
a=lambda x:max(x)
print(a)
print(type(a))
print(a(nums))
运行结果:
<function <lambda> at 0x000001C8FBF72A60>
<class 'function'>
65
7.递归函数
递归算法:在函数或子过程的内部,直接或间接的调用自己的算法。使用地柜算法时必须有一个明确的地柜结束条件,成为递归入口。虽然使用递归算法通常显得很简洁,但递归算法运行效率较低;另外递归的调用过程中系统为每一层的返回点、局部量等开辟了栈来存储,导致递归次数过多时栈溢出,所以一般不提倡用递归算法。
递归算法每次在规模上都要有所缩小,相邻两次的重复之间有紧密的联系,前一次要为后一次做准备,当问题的规模极小时可以给出解答。
下面是一个递归函数,用来求阶乘:
a= 5
def GetMul(num):
if num==1:
return 1
elif num>1:
return GetMul(num-1)*num
result=GetMul(5)
print(result)
运行结果如下:
120
递归深度
获得递归深度:
import sys
print(sys.getrecursionlimit())
python中默认的递归深度是1000,当递归深度超过这个值时,就会出现异常,解决的方式是手动的设置递归深度:
sys.setrecursionlimit(3003)
print(sys.getrecursionlimit())
运行结果是:
3003