一、函数
1、什么是函数:函数就是具备某一功能的工具
函数的使用必须遵循先定义、后调用的原则
事先准备工具的过程即函数的定义
拿来就用即为函数的调用
函数分为两大类:1、内置的函数 2、自定义的函数
2、为什么要用函数:
2.1 程序的组织结构不清晰、可读性差
2.2 日积月累冗余代码过多
2.3 程序的可扩展性极差
3、怎么用函数
3.1定义函数
3.1.1 语法
#def 函数名(参数1,参数2,参数3,...):#"""#文档注释#"""#code1#code2#code3#...#return 返回值
3.1.2 定义函数阶段发生哪些事:只检测语法,不执行代码
def foo(): #foo=函数的内存地址
print('first')print('sencod')print('asdfsadfasdfas')print('third')
foo()
## 定义阶段
deffoo():print('from foo')
bar()defbar():print('from bar')#调用阶段
foo()
3.1.3 定义函数的三种形式
1.无参函数
defbar():print('from bar')
bar()
2.有参函数
deffunc2(x,y):#x=1
#y=3
if x >y:print(x)else:print(y)
func2(1,3)
3.空函数(做占位使用)
deffoo():pass
3.2调用函数
语法:函数名()
调用函数发生了:1、根据函数名找到函数的内存地址 2、函数的内存地址加括号可以触发函数体代码的执行
调用函数的三种方式:
3.2.1 语句
deff1():print('from 1')
f1()
3.2.2表达式
defmax2(x,y):if x >y:returnxelse:returny
res=max(1,2)*10
print(res)
3.2.3当做参数传给其他函数
defmax2(x,y):if x >y:returnxelse:returny
res=max2(max2(1,2),3)print(res)
4、函数的返回值
1、什么是函数的返回值:函数体代码运行的一个成果
return 值:
返回值没有类型限制、返回值没有个数限制
逗号分割多个值:返回一个元组
一个值:返回一个值
没有return:默认返回None
deflogin():whileTrue:
username=input('name>>:').strip()
pwd=input('password>>:').strip()if username not inuser_dic:print('not found')continue
if pwd !=user_dic[username]:print('pwd error')continue
print('login successful')returnusernameprint(login())
return 登录名
#return是函数结束的标志:#函数内可以有多个return,但只要执行一次,整个函数就立即结束,并且将return后的值当作本次调用的结果返回
二、函数的参数
1、函数的参数分为两大类:形参、实参
形参:指的是在定义函数时,括号指定的参数,本质就是变量名
实参:指的是在调用函数时,括号内传入的值,本质就是值
只有在调用函数时才会在函数体内发生实参(值)与形参(变量名)的绑定关系
该绑定关系只在调用函数时临时生效,在调用函数结束后就解除绑定
def foo(x,y): #x=1,y=2
print(x)print(y)#a=1
#b=2
#foo(a,b)
foo(1,2)
2、位置参数
位置形参:在定义函数时,按照从左到右的顺序依次定义的形参称之为位置形参
ps:但凡是按照位置定义的形参,在调用函数时必须为其传值,多一个不行少一个也不行
位置实参:在调用函数时,按照从左到右的顺序依次传入的值
ps:传值是按照顺序与形参一 一对应
deffoo(x,y,z):print(x,y,z)#foo(1,2)
foo(1,2,3,4)#多传一个值 报错#foo(1,2,3)
foo(3,2,1)
3、关键字实参:
在调用函数时,按照key=value的形式定义的实参,称之为关键字实参
注意:
1、在传值时可以完全打乱顺序,但仍然能指定道姓地为指定的参数传值
2、可以在调用函数时,混合使用位置实参与关键字实参
但是位置实参必须跟在关键字实参左边
并且不能为一个形参重复传值
defregister(name,sex,age):print(name)print(sex)print(age)
register(sex='male',name='mogu',age=18)
register('mogu',age=18,sex='male')#混合使用
4、默认参数
在定义函数时,就已经为某些参数绑定值,称为默认参数
ps:1、在定义阶段就已经有值,意味在调用阶段可以不用传值
2、默认形参必须放在位置形参的后面
3、默认形参的值只在定义阶段生效一次,在函数定义之后发生的改动无效
4、默认形参的值通常应该是不可变类型
默认形参:大多数情况下值都一样
位置形参:大多数情况值都不同
def foo(x,y,z=3):print(x)print(y)print(z)
foo(1,2)
foo(1,2,4) #传值后改变了默认值
def register(name,age,sex='female'):print(name)print(sex)print(age)
register('mogu',18)
register('xiaohuochai',28)
register('momo',19)
register('张三',33,'male')
默认与位置示例
m=10
def foo(x,y,z=m):print('x:%s' %x)print('y:%s' %y)print('z:%s' %z)
m=111111111 #定义阶段就是10 此更改无效
foo(1,2)
def foo(name,hobby,l=None):if l isNone:
l=[]
l.append(hobby)print('%s 的爱好是 %s' %(name,l))
l1=[]
foo('mogu','read',l1) #l1=['read']
foo('xiaomogu','movie') #l1=['read','music']
foo('nvhai','卖火柴')
foo('张三','吹牛')
foo('关二爷','耍大刀')
默认形参示例2
5、可变长度的参数
可变长度指的是在调用函数时,函数参数的个数可以不固定
然而实参终究是要为形参传值的,针对两种形式实参个数不固定,对应着形参也必须有两种解决方案
那就是 * 和 ** 来分别处理溢出位置实参与溢出关键字实参
5.1 * 会将溢出的位置实参存成元组,然后赋值给紧跟其后的变量名
5.1.1 形参中带 *
def foo(x,y,*z): #z=(3,4,5,6,7,8)
print(x)print(y)print(z)
foo(1,2,3,4,5,6,7,8)
5.1.2 形参中带* 实参中带 * ,窍门:但凡碰到实参中带* 都先将其打散成位置实参,然后考虑传值
def foo(x,y,*z): #z=(3,4,5,6,7,8)
print(x)print(y)print(z)
foo(1,2,[3,4,5,6,7,8]) #z=([3,4,5,6,7,8],)
foo(1,2,*[3,4,5,6,7,8]) #foo(1,2,3,4,5,6,7,8)====>z=(3,4,5,6,7,8)
foo(1,2,*'hello') #foo(1,2,'h','e','l','l','o')
foo(1,*[2,3,4,5,6]) #foo(1,2,3,4,5,6)
5.1.3 实参中带 * 窍门同上
deffoo(x,y,z):print(x,y,z)
l= ['mogu', 'huochai', 'nvhai']
foo(*l) #foo('mogu', 'huochai', 'nvhai')
5.2 ** 会将溢出的关键字实参存成字典,然后赋值给紧跟其后的变量名
5.2.1 形参中带 **