函数的定义与调用
在python中使用函数分为两个步骤:定义函数、调用函数
定义函数需要用到def关键字
def Cal():
s=3.14*3*3
print("半径为3的园的面积为%.2f"%s)
Cal()
参数列表与返回值
形参
形参的全称是形式参数,即定义函数时函数名后面的一对小括号中给出的参数列表。
形参只能在函数中使用,其作用是接收函数调用时传入的参数值并在函数中参与运算。
实参
实参的全称是实际参数,即在调用函数时函数名后面的的一对小括号中给出的参数列表。
当调用函数时,会将实参的值传递给对应的形参,函数中再利用形参做运算,得到结果。
默认参数
函数的默认参数就是缺省参数,即当调用函数时,如果没有为某些形参传递对应的实参,则这些形参会自动使用默认参数值。
def StudentInfo(name,country="中国"):
print("姓名:%s,国家:%s"%(name,country))
StudentInfo("liming")# 没有传国家,但是因为有默认参数,所以不会出错
StudentInfo("lihong","美国")
关键字参数
在使用关键字参数调用函数时,实参的传递顺序可以与形参列表中形参的顺序不一样。这样,当一个函数的很多参数都有默认值,而我们只想对其中一小部分带默认值的参数传递实参时,就可以直接通过关键字参数的方式来进行实参传递,而不必考虑这些带默认值的参数在形参列表中的实际位置。
def StudentInfo(name,chineseLeve="good",country="中国"):
print("name:%s,chineseLeve:%s,country:%s"%(name,chineseLeve,country))
StudentInfo("xiaoming")# 没有传递chineseLeve和country但是因为有默认参数,所以不会出错。
StudentInfo("UZI",country="china")# 没有传递chineseLeve但是因为有默认参数,所以不会出错。
StudentInfo(country="k",chineseLeve="bad",name="shy")# 改变顺序
不定长参数
不定长参数,即在调用函数时可以接收任意数量的实参,这些实参在传递给函数时会被封装成元组或字典形式。一般情况下,不定长参数放在形参列表的最后,前面传入的实参与普通形参一一对应,而后面剩余的实参会在被封装成元组或字典后传给不定长参数。
def StudentInfo1(name,*args):# 一个*表示这个不定长参数对应的是一组位置参数
print("name:",name ,",others:",args)
def StudentInfo2(name,**args):# 两个*表示这个这个不定长参数对应的是一组关键字参数
print("name:",name ,",others:",args)
def StudentInfo3(name,*args,country="china"):
print("name:",name ,"Country:",country,"others:",args)
StudentInfo1("a","good","china")
StudentInfo2("a",english="good",country="china")
StudentInfo3("b","good","19",country="china")
拆分参数列表
如果一个函数所需要的参数已经存储在列表、元组或字典中,就可以直接从列表、元组或字典中拆分出函数所需要的参数,其中列表、元组拆分出来的结果作为位置参数、而字典拆分出来的结果作为关键字参数。
def SumVal(*args):
sun=0
for i in args:
sum+=i
print("the final answer is: ",sum)
ls=[3,5,4,7,1]
SumVal(ls[0],ls[1],ls[2],ls[3])
模块
在一些大型项目中,我们需要将代码分门别类的放在不同的脚本文件中,这些脚本文件称为模块。
猴子补丁
猴子补丁是指在运行时动态替换已有的代码,而不需要修改原始代码。
def Sum(a,b):
print("SUM")
return a+b
def NewSum(*args):
print("NWESUM")
s=0
for i in args:
s+=i
return s
Sum=NewSum # 直接将Sum替换成NewSum
print(Sum(1,2,3,4,5,6))# 运行Sum会得到NewSum的结果
变量的作用域
global关键字
global关键字可以声明在该函数中使用的是全局变量而非局部变量。
def GlobalVar1():
print("GlobalVar1中的X是值为:",x)
def GlobalVar2():
global x
x=100
print("GlobalVar2中的X是值为:",x)
x=20
GlobalVar1()# x=20
GlobalVar2()# x=100
GlobalVar1()# x=100
nonlocal关键字
在python中,函数的定义可以嵌套,即在一个函数的函数体中可以包含另一个函数的定义。
通过nonlocal关键字,可以使内层的函数直接使用外层函数中定义的变量。
#不使用nonlocal
def outer():
x=10
def inner():
x=20
print("inner函数中的X值为",x) #结果为20
inner()
print("outer函数中的X值为:",x)#结果为10
outer()
#使用nonlocal
def outer():
x=10
def inner():
nonlocal x
x=20
print("inner函数中的X值为",x)# 结果为20
inner()
print("outer函数中的X值为:",x)# 结果为20
outer()
nonlocal与global的区别
nonlocal:用于嵌套函数可以使内层的函数直接使用外层函数中定义的变量。
global:用于多个没有嵌套关系的函数,声明在该函数中使用的是全局变量而非局部变量。
高级应用
高阶函数
所谓高阶函数就是把函数作为参数的一种函数。
def FunAdd(f,x,y):
return f(x)+f(y)
def Square(x):
return x**2
def Cube(x):
return x**3
print(FunAdd(Square,3,-5))
print(FunAdd(Cube,3,-5))
lambda函数
lambda函数也称为匿名函数,是一种不使用def定义函数的形式,其作用是能快速定义一个简短的函数。lambda函数的函数体只是一个表达式,所以lambda函数通常只能实现比较简单的功能。
def FunAdd(f,x,y):
return f(x)+f(y)
# labbda表达式:有一个参数x,返回值是X的平方。
print(FunAdd(lambda x:x**2,3,-5))# 即计算3的平方+(-5)的平方
print(FunAdd(lambda x:x**3,3,-5))# 即计算3的3方+(-5)的3方
闭包
如果内层函数使用了外层函数中定义的局部变量,并且外层函数的返回值是内层函数的引用,就构成了闭包。
定义在外层函数中但由内层函数调用的变量称为自由变量。一般情况下,如果一个函数结束,那么该函数中定义的局部变量会全部释放。然而,闭包是一种特殊情况,外层函数在结束时会发现其定义的局部变量将来会在内层函数中使用,此时外层函数就会把这些自由变量绑定到内层函数。所谓闭包,实际上就是将内层函数的代码以及自由变量(由外层函数定义,但会由内层函数使用)打包在一起。
def outer(x):
y=10
def inner(z):
nonlocal x,y
return x+y+z
return inner #返回嵌套函数inner的引用
f=outer(5)
g=outer(50)
print("the value of f(20) is :",f(20))
print("the value of g(20) is :",g(20))
print("the value of f(30) is :",f(30))
print("the value of g(30) is :",g(30))
# 通过f=outer(5)将outer 返回的inner 函数的引用赋给了f,此时outer函数中的两个局部变量x (=5)和y (=10)也同时绑定到返回的inner函数,形成了一个闭包;在调用f(20)时,会将20传给f所对应的inner函数的形参z,因此f(20)最后返回的计算结果为x+y+z=5+10+20=35;类似地,在第11行调用f(30)时,会将30传给f所对应的inner 函数的形参z,因比f(30)最后返回的计算结果为x+y+z=5+10+30=45。
装饰器
利用装饰器,可以在不修改已有函数的情况下向已有函数中注入代码,使其具备新的功能。
装饰器实际上就是一个闭包
# 定义装饰器1
def deco1(func):#形参func接收要装饰的函数
def inner1(*args,**kwargs):# (*args,**kwargs)表示inner1可以具有任意形式的形参列表
print("deco1 begin")
func(*args,**kwargs)# 执行要装饰的函数的代码
print("deco1 end")
return inner1
# 定义装饰器2
def deco2(func):
def inner2(*args,**kwargs):
print("deco2 begin")
func(*args,**kwargs)
print("deco2 end")
return inner2
# 将装饰器1的代码注入到F1中
@deco1
def f1(a,b):
print("a+b=",a+b)
# 当一个函数前面有多个装饰器时,安装从后往前的顺序依此装饰。即:先执行@deco2,后执行@deco1
@deco1
@deco2
def f2(a,b,c):
print("a+b+c=",a+b+c)
if __name__=="__main__":
f1(3,5)
f2(1,2,3)