函数能够提高应用的模块性,和代码的重复利用率,用来实现单一、相关联的功能的代码段
定义一个函数
我们可以定义一个实现自己想要实现的功能的函数,实现规 则如下:
- 函数的代码块是以def关键词开头的,后接函数标识符和圆括号()
- 圆括号中放传入的参数和自变量,圆括号之间可以用于定义参数
- 函数的第一行语句可以使用文档字符串,编写函数说明
- 函数内容以冒号:开始,并且注意缩进
- 结束函数用return [表达式] ,可以选择一个值返回给调用方,也可以不返回任何表达式,代表返回None
语法
def 函数名(参数列表):
函数体
案例1:使用函数输出“Hello World”
#使用函数输出“Hello World”
def test(): #定义函数
print("Hello World")
test() #调用test()函数会输出“Hello World”
案例2:比较两个数的大小,并返回较大的数
#比较两个数的大小,并返回较大的数
def max(a,b): #定义函数,并传入a,b两个参数
if a>b: #判断两个参数大小
return a #返回a
else:
return b #返回b
a=6 #给参数a赋值
b=9 #给参数b赋值
print(max(a,b)) #输出这个函数
案例3:计算面积函数
#计算面积函数
def area(width,height): #定义函数
return width*height #返回面积表达式
width=4 #给宽赋值
height=5 #给高赋值
print("width:",width,"height:",height,"area:",area(width,height)) #输出
函数调用
#定义函数
def printme(str):
#打印任何传入的字符串
print(str)
return
#调用函数
printme("送你一朵小红花~")
printme("来年喜乐有钱花~")
参数传递
在Python中,对象是有类型的,而变量是没有类型的
a=[1,2,3,4]
a="你好,明天!"
[1,2,3,4]是list类型,你好,明天!是String类型,变量a是没有类型的,它仅是对象的引用(指针),可以是指向list类型对象,也可以是指向String类型对象
可更改(mutable)与不可更改(immutable)对象
在Python中,strings,tuples,numbers是不可更改的对象;list,dict...是可更改对象
#不可变对象
def noChange(a):
#利用id()函数查看内存地址变化
print(id(a)) #指向的是同一个对象
a=10
print(id(a)) #一个新对象
a=1
print(id(a))
noChange(a)
#调用函数之后,形参和实参指向的是同一个对象,在对象内部修改形参之后,形参指向的是不同的对象
结果:
1906755201328
1906755201328
1906755201616
#可变对象
def Change(mylist):
#修改传入的列表
mylist.append([1,2,3,4])
print("函数内取值",mylist)
return
#调用函数
mylist=[6,7,8]
Change(mylist)
print("函数外取值",mylist)
#传入函数的和在末尾添加新内容的对象用的是同一个引用
结果:
函数内取值 [6, 7, 8, [1, 2, 3, 4]]
函数外取值 [6, 7, 8, [1, 2, 3, 4]]
参数
必需参数
需以正确的顺序传入函数,调用时的数量必须与声明时的一致(至少传入一个参数)
#不传参时报错案例
def test(str):
print(str)
return
test()
结果:
Traceback (most recent call last):
File "D:\Python_test\day1\def\test7.py", line 5, in <module>
test()
TypeError: test() missing 1 required positional argument: 'str'
#正常传参结果
def test(str):
print(str)
return str
test("你好,明天!")
结果:
你好,明天!
关键字参数
关键字参数与函数调用关系紧密,函数调用使用关键字参数来确定传入的参数值(关键字参数允许传参与声明时的顺序不一致,解释器能够使用参数名匹配参数值)
def test(name,age):
print("名字:",name)
print("年龄:",age)
return
test(age=10,name="啾咪")
结果:名字: 啾咪
年龄: 10
默认参数
调用函数时,如果没有传入参数,则会使用默认参数
def test(name,age=18):
print("名字:",name)
print("年龄:",age)
return
test(name="啾咪")
结果:
名字: 啾咪
年龄: 18
不定长参数
利用函数来处理比命名时更多的参数,基本语法如下
def functionname([formal_args,] *var_args_tuple ):
"函数_文档字符串"
function_suite
return [expression]
def test(age,*vartuple):
print("输出:")
print(age)
print(vartuple)
test(77,33,11,22)
结果:
77
(33, 11, 22)
如果在函数调用时没有指定参数(空元组),外面可以不向函数传递未命名的变量
# 可写函数说明
def printinfo(arg1, *vartuple):
"打印任何传入的参数"
print("输出: ")
print(arg1)
for var in vartuple:
print(var)
return
# 调用printinfo 函数
printinfo(10)
printinfo(70, 60, 50)
结果:
输出:
10
输出:
70
60
50
参数带两个**号的基本语法
有两个"**"号的参数,会以字典的形式导入
def functionname([formal_args,] **var_args_dict ):
"函数_文档字符串"
function_suite
return [expression]
#可写函数说明
def test(age,**name):
#打印任何传入的参数
print("输出:")
print(age)
print(name)
#调用test函数
test(1,a=3,b=4)
声明函数时,参数中的"*"可以单独存在,如果单独出现时,"*"后的参数必须用关键字传入,否则会报错
def f(a,b,*,c):
return a+b+c
#调用函数
f(1,2,c=3)
匿名函数
匿名函数没有指定的函数名,由lambda来创建匿名函数
- lambda只是一个表达式,函数体比def简单很多
- lambda是一个表达式,不是代码块,只能在lambda表达式封装有限的逻辑进去
- lambda函数有自己的命名空间,不能访问自己参数列表之外的参数/全局命名空间里的参数
匿名函数的语法:
lambda [arg1 [,arg2,.....argn]]:expression
#可写函数说明
sum=lambda arg1,arg2:arg1+arg2
#调用函数
print("输出:",sum(10,20))
强制位置参数
强制位置参数指明函数形参必须使用指定位置参数,不能是使用关键字参数的形式
案例:a,b为强制位置参数、c,d为位置形参/关键字形参、e,f为关键字形参
def f(a, b, /, c, d, *, e, f):
print(a, b, c, d, e, f)
f(10,10,30,d=40,e=60,f=60)