(1)函数就是把完成特定功能的代码封装起来 (代码缩进)
(2)给该功能起一个名字(函数名),哪里需要实现该功能就在哪里调用该函数。
(3)函数可以在任何时间和地方调用
(4)所谓函数,就是把具有独立功能的代码块组织为一个小模块,在需要时调用。
注意:函数名的规范
(A)字母、数字,下划线,但不能以数字开头 (B)不能使用关键字或保留字 (C)多个单词使用下划线命名: get_num()
2.函数的定义方式
def 函数名(形参1,形参1...): 函数体
1 def func(): 2 for i in range(3): 3 print("hello world") 4 5 func() 6 7 执行结果: 8 hello world 9 hello world 10 hello world
提示:定义函数使用def关键字,如果要返回值则可以使用return。如果函数执行完毕后没有使用return返回值,或者使用return结束函数但是没有指定返回值,默认就会返回None
-
def 是定义函数的关键字。
-
函数名是这个函数的符号,调用这个函数的时候,我们需要函数名。
-
函数名后的圆括号是必须的
-
圆括号后面必须有一个分号
3调用函数:
语法:函数名(实参)
-
定义函数的目的是为了让函数做一些事情,但是函数如果仅仅定义是不会自己去执行
-
所以时刻记住一句话,函数只有被调用才能被执行!
-
所以想要函数执行,必须去调用函数。
-
在使用函数的时候,一定要保证声明在前,调用在后!
#定义函数
def func():
for i in range(10): #函数体
print("hello world") #函数体
#函数调用
func()
3.1简单的函数调用
函数调用非常简单,语法: 函数名(实参) 。当然如果函数定义的时候没有形参,则就不用实参。
1 #定义无参数函数 2 def show(): 3 print("我是函数内的代码1") 4 print("我是函数内的代码2") 5 6 #无参数函数调用 7 show() 8 9 show() #一个函数可以多次调用。每次调用都会执行一次函数体的代码 10 11 执行结果: 12 我是函数内的代码1 13 我是函数内的代码1 14 15 我是函数内的代码1 16 我是函数内的代码1
3.2带形参的函数调用
函数声明的时候,在括号内的是形参。
那么在调用函数的时候应该传递相同属性的参数过去,函数调用的时候的参数,叫做实参!
语法:函数名(实参1,实参2,。。。)
#定义带参数的函数
def add(a, b):
print(a + b)
#调用时,需传入相同属性数据类型的实参
add(2, 3)
add(20, 3)
执行结果:
5
23
4.函数的作用:
-
函数是能够完成某一功能的代码段
-
函数是可重复执行的代码段
-
函数方便管理和维护,便于复用
5.函数的参数
函数声明的时候,有参数,是希望外界向函数内传递内容,故在括号内的是形参。那么在调用函数的时候应该传递相同属性的真实参数过去,函数调用的时候的参数,叫做实参!
5.1函数参数的分类
5.1.1按照是否是可变类型分:不可变类型 和 可变类型
(1)不可变类型:
值的内容改变,地址也发生改变了
1 #声明定义函数,传入不可变数据类型 2 def fun(name): 3 print("----1111111",id(name))#------------->6430944 4 if name !="admin": 5 print("---22222",id(name))#------------>6430944 6 name="admin123" 7 print("---33333",id(name))#------------->6424800 8 9 name=ad 10 print("----4444",id(name))#--------------------->6430944 11 #调用函数 12 fun(name) 13 print("----5555",id(name))#--------------------->6430944
(2)可变类型:
如果传入的是可变类型,比如列表,函数里改变了列表的排序。则会影响到外部变量对应的列表,因为它俩的值地址指向是一样的。值的内容发生改变,但是地址不发生改变.
#定义函数,传入可变数据类型
1 def fun(l): 2 print(id(l))#---------------3737920 3 print(l)#--------------[2,5,1,3,8,7] 4 l.sort() 5 print(id(l)))#---------------3737920 6 print(l)#--------------[1,2,3,5,7,8] 7 8 list1=[2,5,1,3,8,7] 9 print(id(list1)))#---------------3737920 10 #调用函数,传入实参列表 11 fun(list1) 12 13 print(list1)#--------------[1,2,3,5,7,8] 14 print(id(list1)))#---------------3737920
5.1.2按照参数的类型:默认参数、关键字参数、可变参数
(1)默认值参数
默认值参数:在函数定义的时候,设置的.
-
(A)默认值赋值的时候只要负责默认值前面的赋值
-
(B)不想使用默认的值,则传递一个值(传递的值覆盖原来的了)
-
(C)非默认值的元素必须在默认值的前面,如果在后面则语法错误
-
(D)如果有多个默认值,只想改变其中的某一个,使用:关键字=新值
-
(E)默认值是列表(可变类型),固定不变的地址。该可变的类型就是共享空间。注意:默认值是可变类型的,则在定义的时候,内存地址就固定了。
-
(F)后一个默认值不能引用前一个默认值,如果引用则报错
案例一:默认值赋值的时候只要赋值默认值前面的赋值
#定义一个有默认值参数函数
def func(a,b=5):
return a+b
#调用函数,如果想使用b默认值,则只需要传入一个实参赋值给a
fun(2)
执行结果:
7
案例二:不想使用默认的值,则传递一个值(传递的值覆盖原来的了)
def func(a,b=5):
return a+b
#调用函数,如果不想使用b默认值,则实参传入一个新值,就会覆盖默认值了
fun(2,10)
执行结果:
12
案例三:非默认值的元素必须在默认值的前面,如果在后面则语法错误
def func(a,b=2,c):
return a+b+c
fun(2,4,5)
执行结果:
SyntaxError:non-default argument follows default argument
案例四:如果有多个默认值,只想改变其中的某一个,使用:关键字=新值
def login(username,password="1234",count=3):
for i in range(count):
if username="admin" and password="1314":
print("登录成功!")
break
else:
print("第%d登录失败!"%(i+1))
#调用函数
login("admin",password="1314")
案例五:默认值是列表(可变类型),固定不变的地址。该可变的类型就是共享空间
def func(a,b=[]):
b.append(a)
fun("马思纯")----->["马思纯"]
fun("周冬雨")----->["马思纯","周冬雨"]
fun("刘若英")----->["马思纯","周冬雨","刘若英"]
案例六:后一个默认值不能引用前一个默认值,如果引用则报错
def func1(x,y=5,z=y):
print(x,y,z)
func1(8)
执行结果:
NameError:name "y" is not defind
(2)关键字参数
-
关键字参数明确赋值
关键字:拿到形参名字,明确的赋值。好处,可以明确赋值,顺序可以对调
-
使用关键字改变默认值
def func1(x=1,y=2,z=3): #定义默认值
print(x,y,z)
func1()
func1(x=8)=====>关键字改变默认值
(3)可变参数
def func(*args,**kwargs)
*args :单个元素 "奥特曼"
**kwargs:成对出现 name="奥特曼"
在形参前面添加一个 *号, 这样的参数就是可变参数, 可以接受任意多个参数.
def foo(a, *b): # b 就是可变参数, 在函数内部可以作为元组使用
print(a)#------->10
print(b)#------->(20,4,7,9)
foo(10, 20, 4, 7, 9)
解析:
在python解释器中,当遇到函数形参带*时,就会准备一个空元组来装包,实参传入,就装包在一个元组里并赋值给形参带*变量。
在形参前面添加一个 **号, 这样的参数就是可变参数, 可以接受任意多个参数.
def test(**kwargs):
print(type(kwargs),kwargs)
test1()
test1(song1="听海")
test1(name="阿妹",song="听海")
执行结果:
<class 'dict'> {}
<class 'dict'> {'song1': '听海'}
<class 'dict'> {'name': '阿妹', 'song': '听海'}
定义一个万能参数
def funcA(*args,**kwargs):
if len(args)>0:
for i in args:
print("args:---->",i)
if len(kwargs)>0:
for key,value in kwargs.item():
print(key,"--",value)
funcA()
funcA("英雄联盟")
funcA("英雄联盟","绝地求生")
funcA("英雄联盟",player1="faker",player2="小明")
会报错,只要有关键字参数存在以后的参数必须是关键字
funcA(player1="faker","英雄联盟","绝地求生")
*就是一个分隔符,用于分割前面的单个元素和后面的关键字赋值
def func2(a,b,*,age,name):
print(a)
print(b)
print(name)
print(age)
func2(1,2,age=18,name="马思纯")
6.返回值return
-
只要函数有返回值,则必须接收
-
在函数里 return 会结束函数,后面的代码不再执行
-
只能结束循环体,会继续执行下边的代码
提示:参数:外界往里面送值 返回值:函数里面向外界送值
def login(userName,passWord):
if userName=="admin"and passWord=="1234":
print("登录成功!")
return True
else:
print("登录失败!")
def pay(money):
if login():
print("付款金额为:",money)
print("正在付款....")
print("付款成功!")
特殊的返回值:可以接收多个返回值
def func ():
a="hello"
b="world"
list1=[1,2,3,4,5]
return a,b,list1
n1,n2,n3=func()
print(n1)
print(n2)
print(n3)
7.递归函数
函数内部自己调用自己
8.匿名函数
1.什么是匿名函数?
函数没有名称。关键字 lambda 来定义匿名函数。匿名函数有个限制,就是只能有一个表达式,不用写return,返回值就是该表达式的结果。
匿名函数主要作为参数出现:可参照 sort(key=function)。结合系统函数使用较多
2.匿名函数的定义方式
lambda 形参列表:表达式
例如:f=lambda x:x+1
f=lambda x:x+1
r=f(5)
print(r)
执行结果:
>>>6
定义一个匿名函数的流程:
(1)定义匿名函数lambda表达式 lambda x : x+1
(2)将lambda表达式赋值给一个变量 f=lambda x : x+1
(3)f就是匿名函数,调用:f(实参)
(4)接收f函数调用的结果, result=f(实参)
案例一:求三个数的和
f=lambda x,y,z:x+y+z
result=f(1,2,3)
print(result)
执行结果:
>>>6
案例二:传一个字符串,返回字符串的大写形式
f=lambda s : s.upper()
result=f("abc")
print(result)
执行结果:
>>>ABC
案例三:传一个列表,返回升序结果
f=lambda l : l.sort()
ll=[5,3,1,7,9,0]
f(ll)
print(ll)
执行结果:
>>>[0,1,3,5,7,9]
解析:由于l.sort()没有返回值,是对原列表进行升序操作,所有f就不用接受返回值。
案例四:函数作为参数
def func(f): #f=lambda x,y:x+y
if callable(f):
result=f(1,4)
print("result",result)
func(lambda x,y:x+y)
执行结果:
>>>5
案例五:按照年纪升序排序
lists=[("梅西",33),("C罗",30),("内马尔",26),("凯恩",28)]
def func2(t):
return t[1]
lists.sort(key=func2)
print(lists)
执行结果:
>>>[("内马尔",26),("凯恩",28),("C罗",30),("梅西",33)]
解析:底层是拿出列表的一个元素给函数的形参t :t=("梅西",33)
return t[1]-------->表示的是扔出来的是一个年龄
key=func2---------->按照关键字func2返回的值进行排序
案例六:利用匿名函数按照年纪升序排列
lists=[("梅西",33),("C罗",30),("内马尔",26),("凯恩",28)]
lists.sort(key=lambda x:x[1])
print(lists)
执行结果:
>>>[("内马尔",26),("凯恩",28),("C罗",30),("梅西",33)]
list2=[{"name":"马思纯","age":30},{"name":""周冬雨,"age":24}]
list2.sort(key=lambda x:x["age"])
print(list2)
执行结果:
>>>[{"name":""周冬雨,"age":24},{"name":"马思纯","age":30}]
9.高阶函数
1.什么是高阶函数
(1)一个可以接收函数作为参数的函数称为高阶函数
(2)函数作为结果返回
案例一:函数作为一个参数传入另一个函数的高阶函数
def func(a,b,f): ------------>#a=n1 b=n2 f=f1
return f(a)+f(b) --------> #f1(n1)+f1(n2)
def f1(m):
return m**2
n1=2
n2=4
func(n1,n2,f1)
result=func
print(result)
执行结果:
>>>20
案例二:函数作为结果返回
def outer():
a=100
def inner():
b=80
c=a+b
print(a,b,c)
return inner
f=outer()
result=f()
执行结果:
>>>100 80 180
2.常用的高阶函数
map() filter() reduce()
2.1 map(function,iterable)
map:映射 ------->在built-in function模块中,无需引入,直接可调用
案例一:使一个列表中的每个元素都加2
result=map(lambda a :a+2,[1,2,3,4,5,6])
print(list(result))
执行结果:
>>>[3,4,5,6,7,8]
案例二:使两个列表里的元素相加,得到一个新列表
result=map(lambda a,b:x+y,[2,4,5,7],[1,6,9])
print(list(result))
执行结果:
>>>[3,10,14]
案例三:使一个列表中的字符串元素的首字母都是大写
result=map(lambda s:s.title(),["hello","tom","jack"])
print(list(result))
执行结果:
>>>["Hello","Tom","Jack"]
2.2filter(function,iterable) 过滤
function的返回值必须是布尔类型
案例一:利用filter过滤一组数,得到这组数中的偶数
result=filter(lambda x:x%2==0,(1,2,3,4,5,6,7))
print(list(result))
执行结果:
>>>(2,4,6)
案例二:利用filter过滤一组数据,得到这组中所有的数字
result=filter(lambda x: x.isdigit(),["hello","1","9","tom"])
print(list(result))
执行结果:
>>>[1,9]
案例三:["hello","1","9","tom"]找出里面的非数字元素,并将里面的首字母大写
list1=["hello","1","9","tom"]
result=filter(lambda s:s.isalpha(),list1)
result=map(lambda a:a.title(),list(result))
print(list(result))
执行结果:
>>>["Hello","Tom"]
2.3functools.reduce(function,iteranle[,intializer])
reduce 在functools模块里,所以在引用reduce需要引入functools模块
案例一:对一组数,利用reduce实现累加和
import functools
result=functools.reduce(lambda x,y:x+y,[1,2,3,4])
print(result)
执行结果:
>>>10
解析:reduce 在底层其实是个递归过程,第一次x=1,y=2,结果等于3,赋值给x=3,y再取列表的一个元素,y=3。这时x+y=3+3=6 ,再将结果6赋值给x=6。y再取列表的一个元素,y=4, 此时x+y=10.
案例二:reduce的初始化值
import functools
result=functools.reduce(lambda x,y:x+y,[1,2,3,4,5],5)
print(result)
执行结果:
>>>20
解析:
默认值5,第一次会赋值给x=5,y从列表取一个元素,y=1,此时x+y=6
第二次,x+y=6的结果重新赋值给x=6, y从列表中取一个元素y=2,此时x+y=8
第三次,x+y=8的结果重新赋值给x=8, y从列表中取一个元素y=3,此时x+y=11
以此类推。。。
最终得出结果为20
案例三,利用reduce统计一个字符串里一个字母出现的次数
s="abc hsiue hdui jeda abc wkahd djoad wjdoaj djoad abc wjdoadjam
dao abc wjdai djao dhiaw jad jfp abc"
import functools
result=functools.reduce(lambda x,y:x+y.count("abc"),s.split(),0)
print(result)
执行结果:
>>>5
10.闭包
1.什么是闭包
外层函数+内层函数,并且返回值是内层函数
(1)函数里有内层函数
(2)将内层函数作为结果返回
案例一:按照闭包的方式完成:外层函数接收一个列表参数,内层函数只对列表中的数字部分进行累加求和
import functools
lists=["aa","3","b","8","5","e"]
def outer(l):
def inner():
result=filter(lambda x:x.isdigit(),l)
new_list=list(result)
result2=functools.reduce(lambda x,y:int(x)+int(y),new_list)
return=result2
return inner
f=outer(list2)
result=f()
print(result)
执行结果:
>>>16
2.闭包参数的几种形式:
(1)外层无参数,内层无参数
(2)外层有参数,内层无参数
(3)外层无参数,内层有参数
(4)外层有参数,内层有参数
(5)外层有返回值,内层有返回值
案例三:外层无参数,内层有参数
def outer():
content=input("请输入姓名")
def inner(number):
for i in range(number):
print("%s说,今天天气真好!"%content)
return inner
f=outer()
f(3)
执行结果:
>>>
请输入姓名:马思纯
"马思纯说,今天天气真好!"
"马思纯说,今天天气真好!"
"马思纯说,今天天气真好!"
案例四:外层有参数,内层有参数
def outer(friend):
name=input("请输入姓名")
def inner(number):
for i in range(number):
print("%s邀请%s一起出去玩!"%(friend,name))
return inner
f=outer("马思纯")
f(3)
执行结果:
请输入姓名:周冬雨
"马思纯邀请周冬雨一起出去玩!"
"马思纯邀请周冬雨一起出去玩!"
"马思纯邀请周冬雨一起出去玩!"
案例五:外层有返回值,内层有返回值
import random
def outer(friend):
name=input("请输入姓名")
def inner(number):
n1=0
n2=0
print("=====%s大战%s====="%(friend,name))
for i in range(number)
ran1=random.randint(1,7)
ran2=random.randint(1,7)
if ran1>ran2:
n1+=1
print("ran1:%d PK ran2%d,此局游戏获胜者是:%s"(ran1,ran2,friend))
elif ran1==ran2:
print("平局")
else:
n2+=1
print("ran1:%d PK ran2:%d,此局游戏获胜者是:%s"%(ran1,ran2,name))
if n1>n2:
return friend
else:
return name
return inner
f=outer("马思纯")
r=f(3)
print("获胜者是:"r)
执行结果:
请输入姓名:周冬雨
ran1:7 PK ran2:5,此局游戏获胜者是:马思纯
ran1:2 PK ran2:6,此局游戏获胜者是:周冬雨
ran1:6 PK ran2:1,此局游戏获胜者是:马思纯
获胜者是:马思纯
案例六:实现一个简单的计数器
def count_machine(num):
def next():
nonlocal num
temp=num
num+=1
return temp
return next
f=count_machine(0)
while True:
value=f()
print(value)
if value==5:
break
执行结果:
>>>1
>>>2
>>>3
>>>4
>>>5
3.闭包的总结:
-
闭包优化了变量,原来需要类对象完成的工作,闭包也可以完成。
-
由于闭包引用了外部函数的局部变量,则外部函数的局部变量没有及时释放,消耗内存
-
闭包的好处,使代码变得简洁,便于阅读代码。
-
闭包是理解装饰器的基础
4.三层闭包
4.1什么三层闭包
def a1():
a=100
print("a1函数中打印:",a)
def a2():
b=99
print("a2函数中打印:",a,b)
def a3():
c=88
print("a3函数中打印:",a,b,c)
return a3
return a2
f=a1() #------>f=a2
f1=f() #------>f1=a3
f2=f1() #------>a3()
执行结果:
100
100,99
100,99,88
浙公网安备 33010602011771号