函数
1、什么是函数
是实现某一特定功能的代码块的封装
2、函数的分类
系统函数(内置函数) - 系统已经实现了的函(已经造好的机器),只需要调用就可以了
print函数 input函数 len函数 sum函数 max函数等等
自定义函数:程序员自己声明的函数(自己造机器)
3、函数的声明(定义)
1)语法
def 函数名(形参列表):
"""
函数说明文档
"""
函数体
2)说明
def —— python声明函数的关键字
函数名 —— 和变量名一样 见名知意 看到函数名大概知道是用来做什么的
() —— 固定写法
形参列表 —— 变量1, 变量2, 变量3···变量名的个数可以是 0个或多个
它是将函数外面的值传递到函数里面
: —— 固定写法
函数体 —— 和def保持一个缩进的,实现函数功能的一条或者多条语句
3)初学者声明函数的步骤
一、确定函数的功能
二、根据功能确定函数名
三、确定形参,看实现函数的功能需不需要从外面传值,如果需要传值需要几个
四、实现函数功能
五、确定返回值
!!!!!)注意:函数在声明的时候,函数体不会执行
练习:写一个函数求两个数和
# 写一个函数求两个数和
def t_sum(x, y):
"""
函数说明文档(功能说明)
:param x: (参数说明)
:param y:
:return: (返回值说明)
"""
print('求和')
print(x+y)
练习:声明一个函数 实现求1+2+3+。。。n
# 声明一个函数 实现求1+2+3+。。。n
def sum1(n):
"""
求1+2+3+。。。n
:param x:
:return:
"""
i = 0
for x in range(n+1):
i += x
print(i)
sum1(10)
4、函数的调用 使用
1)语法:
函数名(实参列表)
2)说明
函数名 —— 必须是已经声明过的函数
() —— 固定写法
实参列表 —— 数据1, 数据2··· 给形参赋值
同一个函数可以调用多次
3)函数的调用过程(重要*********)
一、回到函数声明的位置
二、用实参给形参赋值 (传参)要保证每一个形参都要有值
三、执行函数体
四、获取返回值
五、回到函数调用的位置,接着往后执行
函数的参数
1、位置参数、关键字参数
调用函数的时候 根据实参的写法分为位置参数、关键字参数
- 位置参数:让实参的顺序与形参一一对应,用逗号隔开
- 关键字参数:以'形参名1 = 值1, 形参名2 = 值2····' 格式来确定实参
- 位置参数+关键字参数:位置参数必须写在关键字参数前
2、参数默认值
声明函数的时候,可以给形参赋默认值
有默认值的形参在函数调用的时候,可以不用给形参赋值
注意:声明的时候,有默认值的参数必须放在最后,当跳过有默认值的参数赋值时,必须使用关键字参数
def func2(a, b=12, c=19):
print(a, b, c)
# 调用函数只给a和c赋值,b使用默认值
func2(13, c=23)
3、参数的类型说明
python中类型只有说明的作用,没有约束的作用,有两种方法:
1)参数赋默认值
2)参数名:类型
4、不定长参数 - 形参的参数不确定
声明函数的时候,在形参前面加*星号,那么这个参数就变成不定长参数,
同时可以接收多个实参(将这个参数变成元祖)必须用位置实参数声明函数的时候,在形参的前面加**两个星号,那么这个参数也会变成不定长参数,
同时可以接收多个实参(将这个参数变成字典)必须用关键字实参数,关键字是key
注意:定长参数必须在不定长参数前面
不带星号的参数要放在带星号参数的前面
练习: 练习:写一个函数,按指定方式计算多个数字的结果
operation('+', '23', '24') ——> 23 + 24
operation('-', '23', '24')
def operation(ex, *a):
if ex == '+':
num1 = 0
for x in range(len(a)):
num1 += x
print(num1)
elif ex == '*':
num1 = 1
for x in range(len(a)):
num1 *= x
练习:写一个函数求多个数的和 既可以使用位置传参,又可以使用关键字传参
def func1(*args, **kwargs):
"""
求多个数的和
:param args:不定长参数 位置参数 整型 元祖
:param kwargs: 不定长参数 关键字参数 字典
:return:
"""
sum1 = 0
print(sum(args))
for key in kwargs:
sum1 += kwargs[key]
print(sum1 + sum(args))
func1(2, 3, 4, a=2, b=3, c=4)
函数的返回值
1、什么是函数的返回值
返回值就是return关键字后面表达式的值,就是函数调用表达式的值
return
函数体中的关键字 只能出现在函数体里
作用:
- 结束函数
- 确定函数返回值
调用函数:执行函数体 获取返回值
函数调用过程: 重要
一、回到函数声明的位置
二、用实参给形参赋值 (传参)要保证每一个形参都要有值
三、执行函数体
四、获取返回值
执行完函数体:函数体执行完、执行过程中遇到return
确定函数返回值:执行函数的过程中有没有遇到return,
如果遇到了,return后表达式的值就是函数的返回值
没有遇到return,函数返回值就是None
五、回到函数调用的位置,接着往后执行(这个时候函数调用表达式的值就是函数的返回值)
2、什么时候需要返回值
如果实现函数的功能,会产生新的数据,就把这个数据作为返回值
return 返回值1,返回值2
匿名函数
什么是匿名函数
匿名函数就是没有名字的函数
1)语法:
lambda 参数列表:返回值
2)说明
lambda - 关键字
参数列表 - 相当于普通函数形参列表
: - 固定写法
返回值 - 相当于普通函数函数体中的return 不能是赋值语句·
注意:
- 匿名函数本质还是函数,函数中的语法绝大多数是适用的
- 匿名函数能做的事情,普通函数都可以做。只是匿名函数简洁
- 不支持通过类型名对参数类型说明
练习:匿名函数求两个数的和
# 匿名函数是一个类型为function的值
fun1 = lambda a, b=1: a+b
print(fun1(1, 2))
print(fun1(a=1, b=2))
print(fun1(1))
函数中的变量
1.变量的作用域
指的是变量的使用范围
全局变量、局部变量
2.全局变量
只要是没有声明在函数中的变量都是全局变量
全局变量的作用域是从变量声明开始到整个py文件结束
3.局部变量
声明在函数中的变量都是局部变量
局部变量的作用域就是从变量声明到函数结束
注意:形参也是局部变量
当调用函数的时候,系统会自动在内存的栈区间为这个函数开辟一个独立的内存区域
用来保存在函数中声明的变量或者产生的数据。当函数调用结束后,这块内存区域会自动销毁
4. global 和 nonlocal
global - 在函数中声明一个全局变量 只能在函数中使用
global 变量名
变量名 = 值
nonlocal - 在局部的局部中修改一个局部变量的值
nonlocal 局部变量名
局部变量名 = 值
x1 = 100
def func4():
# x1 = 200 这个x1是局部变量
global x1 # 说明后面的x1是一个全局变量
x1 = 200
print('函数中', x1)
func4()
print('函数外', x1)
print('0-------------')
def func5():
x2 = 100
def func6():
# x2 = 200
nonlocal x2
x2 = 200
print('函数5的函数6中', x2)
func6()
print('函数5中', x2)
func5()
函数作为变量
1.函数作为变量
python中声明函数其实就是声明一个类型是function的变量
函数名就是变量名
所以普通变量能做的事情函数都可以做
2.一个变量可以给另一个变量赋值
def func1():
return 100
c = func1
c()
print(c())
func1 = 12.5
print(func1)
3.一个变量可以作为一个容器的元素
a = 10 #声明一个变量,类型是整型
print(type(a))
# 声明一个变量,类型是function
def func2():
print('这是函数2')
return 100
print(type(func2))
list1 = [a, func2, func2()]
print(list1)
print('0:', list1[0] // 3)
print('1:', list1[1]()) # print('1:', func2()) -> print('1:', 100)
练习:
list2 = []
for i in range(5):
def func(n):
return i * 2
list2.append(func)
list3 = []
for i in range(5):
list3.append(lambda x: x*i)
print(list3[0](2), list3[1](2), list3[2](2))
"""
list2 = []
i = 0 ~ 4
i = 0: func, list2 = [func]
i = 1: func, list2 = [func, func]
...
i = 4: list2 = [func,func,func,func,func]
"""
# list2[0](3), list2[1](3), list2[2](3)
# func, func, func
# None, None, None
# 0, 2, 3
# 8, 8, 8
print(list2)
print(list2[0](3), list2[1](3), list2[2](3))
4. 变量可以作为函数的参数
函数作为函数的参数(实参高阶函数)
def func1(fn, fn2):
# fn = func11
# fn2 = func12
fn() # func11(), None
print(fn2(3) / 4) # print(9/4)
def func11():
print('这是一个函数')
def func12(n):
# n = 3
return n**2
print(func1(func11, func12)) # print(None)
应用: sort函数 (排序)
nums = [1, 23, 34, 32, 12]
nums.sort() # 从小到大排序
print(nums)
序列.sort函数中有个参数key,这个参数要求传一个函数,并且函数有一个参数和一个返回值
参数就是序列中的元素,返回值就是排序比较的对象
all_stu = [
{'name': 'dd', 'age': 12, 'score': 32},
{'name': 'ad', 'age': 15, 'score': 41},
{'name': 'sd', 'age': 13, 'score': 36},
{'name': 'cd', 'age': 11, 'score': 72}
]
def compare(item):
return item['age']
all_stu.sort(key=compare)
all_stu.sort(key=lambda item: item['age'])
print(all_stu)
all_message = [
('张', 'python1902001'),
('李', 'python1902108'),
('王', 'python1902046')
]
all_message.sort(key=lambda item: item[1], reverse=True)
print(all_message)
all_message.sort(key=lambda item: item[1][-1])
print(all_message)
5.变量作为函数的返回值
将一个函数作为函数的返回值(返回值高阶函数)
def func1():
def temp(*nums):
return sum(nums)
return temp
print(func1()(1, 2, 3, 4))
迭代器 (iter)
1.什么是迭代器(iter)
是容器型数据类型(可以同时存储多个数据),但是想要获取、查看迭代器中元素的值
只能将元素取出来,取出来的元素,在迭代器中就不存在了,去的时候在只能从前往后一个一个的取,不能跳着取
2.迭代器中的元素
迭代器只能通过类型转换将其他容器转换成迭代器,或者通过生成器生成
转换 - 所有序列都可以转换成迭代器。迭代器中的元素可以是任何类型的数据
3.获取元素 -
迭代器获取元素,无论以什么样的方式获取获取后,这个元素在迭代器中就不存在了
- next(迭代器) - 获取迭代器最上的数据
- 遍历获取每一个元素
# 1) next(迭代器) - 获取迭代器最上的数据
iter2 = iter('hello')
print(next(iter2))
print(next(iter2))
print(next(iter2))
print(next(iter2))
print(next(iter2))
# print(next(iter2)) 错误 # StopIteration
# 2) 遍历获取每一个元素
iter3 = iter('hello')
for x in iter3:
print(x)
生成器
1.什么是生成器
生成器本质是迭代器,迭代器不一定是生成器
调用一个带有yield关键字的函数就能得到一个生成器. yield只能在函数体里
def func1():
print('--')
return 100
yield
gen1 = func1()
print(gen1)
2.生成器的元素
生成器获取元素的方式和迭代器一样 next()和 遍历
- 生成器元素的个数:看执行完生成器对应的函数会遇到几次yield
- 元素的值:看yield后表达式的值
3.生成器产生数据的原理
当获取生成器的元素的时候,会执行生成器对应的函数,从开始执行到yield为止,并且将yield后面的数据作为元素返回
并且记录结束位置,下次再获取元素的时候,从上次结束的位置接着往后执行,直到遇到yield,并且将yield后面的数据作为元素返回
以此类推。
如果函数从开始到结束时都没有遇到yield,就获取不到元素。next会报错 for循环会结束
def func2():
print('===')
yield 200
gen3 = func2()
print(next(gen3))
生成式
本质还是生成器 只是写法更简洁
写法:
语法1.
(表达式 for 变量 in 序列)
展开
def func():
for 变量 in 序列:
yield 表达式
func()
() - 固定写法
表达式 - 除了赋值以外的任何语句,如数据、变量、运算表达式、函数调用表达式
一般和后面的变量有联系
for in - for循环
语法2.
(表达式 for 变量 in 序列 if 条件语句)
展开
def func():
for 变量 in 序列:
if 条件语句:
yield 表达式