1.函数是组织好的,可重复使用的,用来实现单一或相关联动功能的代码段
2.语法:
def 函数名(参数列表):
函数体
return XXX; #return返回值,可有可没有,想是啥就是啥,自己定义
例:
def add(a,b):
print(a+b) #一般不让函数内部执行结果
add(3,3); #调用函数并传实参 >>> 6
ret=add(3,3) #给add函数传实参并把函数add的返回值赋给ret变量
print(ret) >>>none 6 #函数add没有返回值所以输出结果为none
3.数据类型:可变类型和不可变类型
1)不可变类型:变量赋值a=5后在赋值a=10,这里实际是新生成一个int值对象10,再让a指向它,而5被丢弃,不是改变5的值,相当于新生成了a。
python函数中的不可变类型的参数传递实际上是值传递(复制副本),如:整数、字符串、元组。如:fun(a),传递的只是a的值,没有影响a对象本身。比如:在fun(a)内部修改a的值,只是修改另一个复制的对象,不会影响a本身。
例:
def fun(a):
a="李四"
print("函数内部:",a) >>>函数内部:李四
a="张三"
print("调用前",a) >>>调用前:张三
fun(a) #调用函数 >>>函数内部:李四
print("调用后",a) >>>调用后:张三
2)可变类型:变量赋值la=[1,2,3,4]后在赋值la[2]=5,则是将list la的第三个元素值更改,本身la没有动,只是其内部的一部分值被修改了。
python函数中的可变类型的参数传递实际上也是值传递(复制副本),只不过传递的数据类型是可变类型,如:列表,字典。如:fun(la),则是将la真正传递过去,修改后fun外部的la也会受到影响。
def fun(nums):
nums[0]="张飞"
nums[1]="刘备"
nums=["燕青","吴用"]
print("调用前:",nums) >>>["燕青","吴用"]
fun(nums)
print("调用后:",nums) >>>["张飞","刘备"]
3)引用传递:在函数内部修改,将影响函数的值。用值传递的传递方式(复制内存地址的副本)去传递,可变类型可改变内容,不可改变原地址。
ff={"悟空","八戒"}
def fun(nums):
nums=ff;
nums=["李逵","武松"]
print("调用前:",nums) >>>["李逵","武松"]
fun(nums)
print("调用后:",nums) >>>["李逵","武松"]
4.函数的正式参数类型:必选参数、默认参数、可变参数、关键字参数和命名关键字参数,这五种参数都可以组合使用,除了可变参数无法和命名关键字混合,但是请注意参数定义的顺序必须是必选参数、默认参数、可变参数、命名关键字参数、关键字参数。
1)必选参数
形参和实参一一对应(个数,数据类型,顺序)
形参:定义方法时的参数
实参:调用方法时的参数
def fun1(a,b):
''' # ''' '''在函数第一行为文档内容
:param a:第一个加数
:param b:第二个加数
return:a+b的和
'''
h=fun1(3,4)
print(h) >>>7
print(fun1.__doc__) #输出文档注释
2)默认参数(缺省参数):必须写在后面,可以指定参数名,但顺序要保证,否则要指定参数名。
def fun1(a=3,b=2):
return a+b;
h=fun1(); #实参有一个时给形参a,实参有两个时则按顺序给形参a和b
print(h); >>>5
def printinfo(name,age=35):
print("名字:",name)
print("年龄:",age)
return;
printinfo('ok') >>>名字:ok
年龄:35
3)命名关键字参数
1.一旦以name=value的传参数的形式存在,以后都要以这种形式存在
2.name=value的传参数的形式,不要求顺序
3.('ok',sorce=30,age=30),后者不能重复以name=value赋值
def show(name,age,sorce=90):
print('姓名:{} 年龄:{} 成绩:{}'.format(name,age,sorce))
#普通的实参直接给值,要求顺序、数据类型、个数一一对应
show(30,'ok') #形同不会报错但逻辑是错误的 >>>姓名:30 年龄:ok 成绩:90
show(sorce=80,age=30,name="ok") #这种逻辑可以不按顺序
show('ok',name='ko',age=30) #会报错,第一个实参默认为name的值与name='ok'相冲突
4)关键字参数(**kw):关键字参数允许你传入0个或任意个含参数名的参数,这些关键字参数在函数内部自动组装成为一个dict(字典)。
def student(name,age,**kw):
print('姓名:{} 年龄:{} other:{}'.format(name,age,kw))
student('tom',30,hao='篮球',ai='足球') >>>姓名:tom 年龄:30 other:{hao:篮球,ai:足球}
dic={"一":123,"二"223:,"三":333}
student('ok',30,**dic) >>>姓名:ok 年龄:30 other:{"一":123,"二":223,"三":333}
注:**kw只拷贝原内容,不会影响到函数外的内容
5)可变参数(不定长参数):可变参数允许你传入0个或任意个参数,这些可变参数在函数调用时自动组装为一个tuple(元组)。
def GetSum(*nums):
sum=0;
for i in nums:
sum+=i;
return sum;
print(GetSum()); >>>0
print(GetSum(2,3,4,5)) >>>14 # *号位置在形参时,可以接受多个值
t=[2,3,4,5]
print(GetSum(t)) >>>报错
print(GetSum(*t)) >>>14 # *号位置在实参时,可以把元组中的每一个元素拿出来单独使用
6)组合参数
def f1(a,b,c=0,*args,**kw):
print('a=',a,'b=',b,'c=',c,'args=',args,'kw=',kw)
args=(1,2,3,4)
kw={'d':99,'x':'#'}
f1('A','B') >>>a=A b=B c=0 args=() kw={}
f1(b='B',a='A') >>>a=A b=B c=0 args=() kw={}
f1(b='B',a='A',c=9) >>>a=A b=B c=9 args=() kw={}
f1(args) >>>报错,因为把元组args当成一个值给了a,形参b没有值,所以报错
f1(*args) >>>a=1 b=2 c=3 args=(4,) kw={}
f1(**kw) >>>报错,没有形参a,b对应的实参 #**kw只能传给形参带两个**号的
f1(*args,**kw) >>>a=1 b=2 c=3 args=(4,) kw={'d':99,'x':'#'}
注:对于任意函数都可以通过类似func(*args,**kw)的形式调用它
7)小结
python的函数具有非常灵活的参数形态,既可以实现简单的调用,又可以传入非常复杂的参数。默认参数一定要用不可变对象,否则程序运行时会有逻辑错误。
1.定义可变参数和**kw关键字参数的语法:
*args是可变参数,args接收的是一个tuple(元组)
**kw是关键字参数,kw接收的是一个dict(字典)
2.传参数
*args会逐个分割args逐个对应形参列表
**只能对应形参列表的**kw
5.变量作用域
1)因为位置不同导致作用域不同,生命周期不同
a=10; #全局变量
def changgeNum():
a=5; #局部变量
print("函数内部:",a)
print("调用前",a) >>>调用前:10
changeNum() >>>函数内部:5
print("调用后",a) >>>调用后:10
2)global在函数内部声明一个全局变量
a=10;
def changgeNum():
global a;
a=5;
print("函数内部:",a)
print("调用前",a) >>>调用前:10
changeNum() >>>函数内部:5
print("调用后",a) >>>调用后:5
3)当全局变量和局部变量重名时,局部变量优先使用,遵循就近一致原则
g_a=10;
def fun1():
g_a=5;
print("函数内部:",(g_a+10))
print("调用前:",g_a) >>>调用前:10
fun1(); >>>函数内部:15 #就近使用变量
print("调用后:",g_a) >>>调用后:10
6.匿名函数
1)python使用lambda来创建匿名函数
2)语法:lambda[参数列表]:函数体内部代码
def fun(a,b):
return a+b;
print(fun(2,2)) >>>4
用lambda表达:
sum=lambda a,b:a+b;
print(sum(2,2)); >>>4
3)委托
def dfdsfe(a,b):
return a+b;
def add(a,b,fun):
print(fun(a,b))
add(11,22,dfdsfe); >>>33
用lambda表达:
def add(a,b,fun):
print(fun(a,b))
add(11,22,lambda a,b:a+b) >>>33
4)lambda内置函数:filter()、map()、reduce()
1.filter():对于序列中的元素进行筛选,最终获取符合条件的序列
foo=[2,18,9,22,17,24,8,12,27]
f=filter(lambda x:x%3==0,foo);
print(list(f)); >>>[18,9,24,12,27]
#用filter(),可以完成很多功能,例如:删除Nome或空字符串
def is_not_empty(s):
return s and len(s.strip())>0;
names=['ko',Nome,'','ok'];
l=list(filter(lambda s:s and len(s.strip())>0,names))
print(l); >>>['ko','ok']
2.map():函数接收两个参数,一个是函数,一个是序列,map将序列的每个元素传入函数中执行,并把结果作为新的list返回。
print(list(map(laambda x:x%2,range(7)))) >>>[0,1,0,1,0,1,0]
3.reduce():对于序列内所有元素进行累计操作
在python 3里,reduce()函数已经被从全局名字空间里移除了,它现在被放置在functools模块里。python中的reduce内建函数是一个二元操作函数,它用来将一个数据集合(链表,元组等)中的所有数据进行操作,用传给reduce中的函数func()(注:必须是一个二元操作函数),先对集合中的第一个和第二个数据进行操作,得到的结果在与第三个数据用func()函数运算,最后得到一个结果。
import _functools #下划线是书写格式,书写规范,也可以去掉
li=(1,2,3,4,5,6,7);
def add(a,b):
return a+b;
total=_functools.reduce(add,li)
print(total); >>>28
用lambda表达:
import _functools
li=(1,2,3,4,5,6,7)
total=_functools.reduce(lambda a,b:a+b,li)
print(total); >>>28
#reduce()还可以接收第三个可选参数,作为计算的初始值。如果把100作为初始值,那么:
v=reduce(f,[1,3,5,7,9],100)
f=lambda a,b:a+b
print(v); >>>125
#python内置了求和函数sum(),但没有求积的函数,请利用reduce()来求积;
li=[2,4,5,7,12]
j=reduce(lambda a,b:a*b,li)
print(j); >>>3360
5)python中自定义排序函数:sorted( )
1.python内置的sorted()函数可对list进行排序
ol=[1,32,13,4,45,16,7]
#用list内置函数sort()进行排序
ol.sort();
print(ol); >>>[1,4,7,13,16,32,45]
#用python内置的sorted()函数可对list进行升序
ul=sorted(ol);
print(ul); >>>[1,4,7,13,16,32,45]
#用python内置的sorted()函数可对list进行降序
ul=sorted(ol,reverse=True); #rexerse默认为False,即升序
print(ul); >>>[45,32,16,12,7,4,1]
#sorted()也是一个高阶函数,它可以接收一个比较函数来实现自定义排序,比较函数的定义是:传入两个带比较的元素x,y,如果x应该排在前面,返回-1;如果x应该在y的后面,返回1;如果x和y相等,返回0。
l=[('Bob',75),('Adam',92),('Bart',66),('lisa',88)]
sor=sorted(l,Key=lambda s:s[1],reverse=True);
print(sor); >>>[('Adam',92),('lisa',88),('Bob',75),('Bart',66)]
#sorted()也可以对字符串进行排序,字符串按照ASCII大小来比较
ol=[('Bob',75),('Adam',92),('bart',66),('lisa',88)]
sor=sorted(l,key=lambda s:s[0],reverse=False)
print(sor); >>>[('Adam',92),('Bob',75),('bart',66),('lisa',88)]
# 通过.lower()方法忽略大小写
sor=sorted(l,key=lambda s:str(s[0]).lower(),reverse=False)
print(sor); >>>[('Adam',92),('bart',66),('Bob',75),('lisa',88)]
2.sorted()和.sort()的区别
1).sort()排序方法
shus.sort()对原有列表进行排序,改变原来列表的顺序,无返回值
print(shus)就是改变后的列表
2)sorted()排序函数
排序时不影响原数据,产生新的排序数据
print(sorted(shus))排序后的结果
print(shus)还是原结果