一 函数知识体系
二 函数基础
三 函数对象、函数嵌套、名称空间与作用域、装饰器
四 迭代器、生成器、面向过程编程
五 三元表达式、列表推导式、生成器表达式、递归、匿名函数、内置函数
什么是函数? 为什么要用函数? 函数的分类:内置函数与自定义函数 如何自定义函数 语法 定义有参数函数,及有参函数的应用场景 定义无参数函数,及无参函数的应用场景 定义空函数,及空函数的应用场景 调用函数 如何调用函数 函数的返回值 函数参数的应用:形参和实参,位置参数,关键字参数,默认参数,*args,**kwargs 高阶函数(函数对象) 函数嵌套 作用域与名称空间 装饰器 迭代器与生成器及协程函数 三元运算,列表解析、生成器表达式 函数的递归调用 内置函数 面向过程编程与函数式编程
函数基础
首先我们需要知道数学函数与编程函数的区别?
数学函数:
编程函数:
写函数是为了一个特定的功能!
为什么要有函数?
- 代码重用
- 保持一致性,易维护
- 可扩展性(后期增加功能)
函数和过程
过程:没有返回值的函数。
返回值
返回值=0:返回None
返回值=1:返回object
返回值>1:返回tuple
函数参数:
形参变量只有在被调用时才分配内存单元,在调用结束时,即刻释放所分配的内存单元。因此,形参只在函数内部有效。函数调用结束返回主调函数后则不能再使用该形参变量。
实参可以是常量,变量,表达式,函数等,无论实参是何种类型的量,在进行函数调用时,它们都必须有确定的值,以便把这些值传给形参。因此应预先赋值,输入等办法使参数获得确定值。
位置参数和关键字参数(标准调用:实参与形参位置一一对应;关键字参数调用:位置无需)位置参数必须在关键字参数左边
默认参数是在函数定义阶段就已经写好了
参数组:非固定长度的参数,**字典 *接收列表。
*args只要是按照位置参数给形参传值,多余的那些值全部都会以列表的是形式存在args当中,都会当做元祖形式去处理,取值的时候加*就会遍历出元组里的所有元素。
**kwargs只要是按照关键字参数给
一,函数的基本使用原则:先定义,后调用
# 先定义后使用
#
# 定义阶段:不会执行函数的代码,只检测语法
# def func():
# print('from func')
# 调用阶段:会触发函数体的代码的执行,直到碰到return结束
# func()
二,# 函数的定义与调用的三种形式
# 有参函数 :定义时有参,调用时也必须传参
# 无参函数
# 空函数
# def func():
# pass
调用函数的三种形式
# 语句形式
# def max2(x,y):
# if x>y:
# return x
# else:
# return y
# max2(22,33)
# 表达式形式
# def max2(x,y):
# if x>y:
# return x
# else:
# return y
# res = max2(22,33)*15
# print(res)
# 把函数的调用当做参数传给一个函数
def max2(max2,y):
if max2>y:
return max2
else:
return y
res = max2(66,99)
max2(res,88)
res = max2(max2(66,99),33)
print(res)
三,函数的返回值
函数处理的结果
作进一步的处理
return 值
注意点
1,函数的返回值没有类型限制
2,函数的返回值没有个数限制(用逗号分隔开),返回元祖的形式
返回多个值:多个返回值用逗号隔开,以元组形式
返回一个值:返回的就是值本身
返回0个值:None,不写也返回None
return 除了有返回的值的功能还有结束函数指定的功能
函数内可以有多个return,但只要执行一次,整个函数就立即结束,并且将return后的值返回
retur 是函数结束的标志
四,函数的参数:
函数分为两大类:
形式参数(形参):在定义函数阶段,括号内定义的参数或者变量名称之为形参。
实际参数(实参):在函数调用阶段,括号内定义的参数或者变量名称之为实参。
补充:在调用函数阶段会将实参的值绑定给形参,这种绑定关系只有调用函数时生效,在函数执行完毕后就会解除。
细分
位置参数:
位置形参:在定义阶段,按照从左到右的顺序依次定义的形参称之为位置形参
特点:但凡按照位置定义的形参,必须被传值,多一个不行少一个也不行
位置实参:在调用阶段,按照从左到右的顺序依次传入的值称之为位置实参
特点:与形参一一对应
关键之实参:在函数调用阶段,按照key=value的形式定义的实参称之为关键字实参
特点:指名道姓的为指定的形参传值,可以完全打乱顺序,但仍能为指定的形参传值
实参的形式可以是位置实参与关键字实参混用,但必须遵循
1,位置实参必须放在关键字实参前面
2,不能对同一个形参重复传值
默认形参:在定义阶段就已经为形参赋值,该形参称之为默认参数
特点:
1,定义阶段就已经有值,意味着调用阶段可以不用传值
2,位置形参必须放到默认形参的前面
3,默认形参的值在函数定义阶段就已经固定死了,定义阶段之后的改动不会影响该值
4,默认形参的值通常应该是不可变类型
可变长参数
可变长实参:指的是在调用阶段,实参的值的个数是不固定的,实参无非是(位置实参,关键字实参),对应着形参也必须有两种解决方案
*----->溢出的位置实参
**----->溢出的关键字实参
def foo(x,y,*z):
print(x)
print(y)
print(z)
foo(1,2,3,4,5,67,)
# 形参中*会将溢出位置的实参全部接收,然后存成元祖的形式,然后把元祖赋值给*后的形参名或者变量名
应用:
def my_sum(*nums):
res = 0
for num in nums:
res+=num
return res
print(my_sum(2,3,4,5,6))
实参中带*的
# 实参中带*的,*会将该参数的值循环取出,打散成位置实参,再与形参做对应
# 注意:以后但凡碰到实参中带*的,他就是位置实参,应该立马打散成位置实参去看
# def foo(x,y,z):
# print(x,y,z)
# foo(1,*[2,3]) #foo(1,2,3)
实参形参都带*的
def foo(x,y,z,*m):
print(x)
print(y)
print(z)
print(m)
foo(1,2,3,4,5,6,7,*[8,9,10,11]) #foo(1,2,3,4,5,6,7,8,9,10,11)
# 约定俗成形参中的*变量名的写法都是:*args
# 形参中某个参数带**的
# 形参中**会将溢出位置的关键字实参全部接收,然后存成字典的形式,
# 然后把字典赋值给**后的形参名或者变量名
# def foo(x,y,**z): #x=1,y=2,z={'b':5,'a':3,'d':4}
# print(x)
# print(y)
# print(z)
#
# foo(1,2,a=3,b=5,d=4)
# 实参的参数也可以带**,该参数必须是字典
# 实参中**,**会将该参数的值循环取出,打散成关键字实参
# 然后把字典赋值给**后的形参名或者变量名
# 注意:但凡碰到实参中带**的,他就是关键字实参,应该立马打散成关键字实参去看
# def foo(x,y,z):
# print(x)
# print(y)
# print(z)
# # foo(1,2,**{'a':1,'b':2,'c':3,'z':4}) #x=1,y=2,b=2,c=3,z=4,a=1
# foo(**{'y':1,'z':2,'x':3})