函数
- 为什么要使用函数?
减少代码的冗余 - 函数先定义后使用(相当于变量一样先定义后使用)
- 函数的分类:
内置函数:python解释器自带的,直接拿来用就行了
自定义函数:根据自己的需求自己定义的函数
def func(): #函数名打印出来的是内存地址
‘’‘注释’’’
函数体 - 函数定义都干了些什么事?
只检测语法,不执行代码 - 函数就是一段功能,尽量把函数名定义的有意义
- 定义函数的三种方式:
有参数的函数:就是接受外部传进来的值,进行一系列的运算,最后吧结果返回出来
无参数的函数:通常只是做一下操作而已
空函数:什么事情都不做就是一个空函数(即便是一个空函数,他也会有如下属性) - 函数的返回值:可返回任意类型的值
什么时候需要有返回值:具体情况具体分析
什么时候没有返回值:具体情况具体分析 - yield和return的区别
yield 停在那呢,挂起了
yield 能返回多次值;return 返回一次值
yield 保存函数状态 - 函数的调用:函数名加()
- 函数参数
形参:定义函数时括号内写的参数
形参在定义阶段是不占内存空间的,在调用的时候才占用内存空间
实参:在调用函数时括号内传进来的值
函数参数的具体用法
1. 位置参数:
1. 按照位置传参
按位置定义的形参必须要传值
按位置定义的实参按照位置与形参一一对应的传
2. 按照关键字传数:按照key=value的形式定义的实参,传的时候与位置没有关系
def foo(x,y):
pass
foo(1,2) #与形参一一对应
foo(y=2,x=1) #关键字参数,指名道姓的传
foo(1,y=2) #混用位置实参和关键字实参
#混着用时:注意:1.不能给同一个形参重复赋值
2.位置实参必须在关键字实参的前面
2. 默认参数:在定义阶段就已经为形参赋值了,意味着在调用阶段就可以不为默认参数传值
如果给默认参数传值了,就把一开始设置的给替换了。
默认参数定义的场景:大多数都是男性,女性很少时就可以设置个默认,当然还有其他场景
注意:1. 默认参数必须在位置形参后面
2. 默认参数的值只在函数定义阶段生效一次,定义之后的修改不会影响它的值
3. 默认参数不要弄成可变类型的,就像是列表,就是一个坑
3. 动态参数
可变长度的参数(长度指的是参数的个数):参数*,**
1. 会把多出来的值传给z,并且以元组的形式返回
2. 会把多出来的值传给z,并且以字典的形式返回
3. 在实参中只要碰到(),就是打散了
只要是可迭代的就可以用
就相当于for循环的操作,遇到先打散
args,**kwargs(可传任意值)
可变长度的参数:从实参的角度推算出形参对应的形式和*
针对按照位置定义的实参多出来的那部分,会被形参中的*处理,并且保存成元组的形式复制给args
针对按照关键字定义的实参多出来的那部分,会被形参中的**处理,并且保存成字典的形式复制给kwargs
def foo(x,y,*args):
print(x,y)
print(args)
print(args[0])
print(*args)
foo(1,2,3,4,5,6,7,8,9)
foo(1,2,3,*(4,5,6,7,8,9))
def bar(x,y,z):
print(x,y,z)
bar(1,2,3)
bar(*['b','a','c'])
bar(*'hel')
bar(*{'a':1,'b':2,'c':3})
def foo(x,y,**kwargs):
print(x,y)
print(kwargs)
print(*kwargs)
def index(x,y,z=1):
print(x,y,z)
def wrapper(*args,**kwargs):
index(args,kwargs)
index(*args, **kwargs)
wrapper(1,2,3)
wrapper(1,2)
wrapper(x=1,y=2)
wrapper(1,y=2)
'''可变长度的参数:从实参的角度推算出形参对应的形式 * 和 **
针对按照位置定义的实参冗余的部分,会被形参中的 * 保存成元组的形式赋值给args
针对按照关键定义的实参冗余的部分,会被形参中的 ** 保存成字典的形式赋值给kwargs
强调:
如果实参中出现了 * 和 **,第一时间打散了去看。
'''
- 命名关键字参数(了解):在定义阶段,在之后定义的形参称为命名关键字参数
特点是:在调用阶段,该参数必须以关键字的形式被传值
def foo(x,y,,a,b):
print(x)
print(y)
print(a)
print(b)
foo(1,2,b=20,a=10)
控制函数调用的时候必须以关键字传参的时候就用命名关键字传参