一、函数
含义:将独立的代码块组织成一个整体,使其具有特殊功能的代码集,在需要的时候再去调用即可
作用:提高代码的重用性,执行体代码看上去更加简练
基本格式
定义函数:
def 函数名():
函数体
调用函数:
函数名()
调用几次,函数里面的代码就会运行几次,每次调用的时候,函数就会从头开始执行
举例:
def say_hello():
print("hello!!,nice to meet you !")
say_hello() # 调用函数前,必须保证函数已经存在
二、返回值
含义:函数执行结束后,最后给调用这的一个结果
作用:
return会给函数的执行者返回值
函数中遇到return,表示此函数结束,不继续执行 (return下面的代码不会执行)
返回值的三种情况:
一个返回值也没有,返回的结果是None
一个返回值,就把值返回给调用者
有多个返回值,以元组的形式返回给调用者
return 和 print 的区别
return 表示此函数结束,print会一直执行
return 是返回计算值,print 是打印结果
三、参数
定义格式
def 函数名(形参a, 形参b):
函数体
……(如a=1,b=2)
注意:形参,定义函数时,小括号里面的变量
调用格式:
函数名(实参1,实参2)
注意:实参,调用函数时,小括号里面的具体的值
def add(a,b): # a, b 就是形参 return a+b print(add(1,2)) # 1,2 就是实参函数参数的类型:
必备参数(位置参数)
含义:传递和定义参数的顺序及个数必须一致
格式:def func(a,b)
注意:写了几个形参必须要传几个,不可多传,也不可以少传
默认参数
含义:为函数提供默认值,调用函数时可不传该默认的值
格式: def func(a=8)
注意:
所有的位置参数必须出现在默认参数前,包括函数定义和调用
设置默认值,没有传值会根据默认值来执行代码,传了值根据传入的值来执行代码(备胎)
可变参数
含义:传入的值的数量是可以改变的,可以传入多个,但也可以不传
格式:def func(*args) # 固定格式 : * +变量 , 一般使用 *args
注意:以元组的形式接收
举例:
def funa(*args): print(args) funa("age",18) # ('age', 18)关键字参数
格式:def func(**kwargs)
注意:以字典的形式接收,传参时一关键字传参;传值的时候需要采用 键=值的形式
作用:可以扩展函数的功能
举例:
def func(**kwargs): print(kwargs) func() # {} func(name="test",age=18) # {'name': 'test', 'age': '18'}注意事项:
args 和 kwargs 是约定俗成的命名,也可以用其他名称(如 *params、**opts),但不推荐;
传参时可通过 * 解包元组 / 列表,** 解包字典(如 func(*[1,2], **{"a":3}));
参数顺序:必备(普通)参数 → 默认参数 → *args → 命名关键字参数 → **kwargs。
四、函数嵌套
嵌套调用:
含义:在一个函数里面调用另一个函数
嵌套定义:
含义:在一个函数中定义另外一个函数
格式:
def study(): print("学习中...") def sleep(): #这是嵌套定义 print("睡觉中...") sleep() #这是嵌套调用 study() #这是调用注意:
注意缩进,定义和调用是同级的,调用如果在定义里面则永远调用不到;
不要在内层函数中调用外层函数,会嵌入死循环,直到超过递归的最大深度;
五、作用域
含义:指的是变量生效的范围,分别是全局变量、局部变量
全局变量:
函数外部定义的变量,在整个文件中都是有效的
函数内部有命名相同的变量没有被覆盖,是因为函数内部如果要使用变量,会先从函数内部找,有的话就直接使用,没有回到函数外面去找
局部变量:
含义:函数内部定义的变量,从定义位置开始到函数定义结束位置有效
作用:在函数体内部,临时保存数据,即当含糊调用完成之后,就销毁局部变量
global :
含义:将变量声明为全局变量;在函数内部修改全局变量,可以使用global关键字
语法格式: global 变量名 (多个变量时,可以用“,”隔开)
总结:global 关键字可以对全局变量进行修改,也可以在局部作用域中声明一个全局变量
nonlocal:
含义:用来声明外层的局部变量,只能在嵌套函数中使用,在外部函数先进行声明,内部函数进行nonlocal声明
总结:nonlocal 只能对上一级进行修改
global_num = 10 #定义全局变量(整个程序可见) def test_global(): global global_num # 声明使用全局作用域的global_num(不加global的话,下面赋值会创建局部变量) print(f"使用global前,global_num:{global_num}") # 读取全局变量 global_num += 5 # 修改全局变量 print(f"使用global后,global_num为:{global_num}") def outer_func(): # 演示nonlocal关键字的嵌套函数) nonlocal_num = 20 # 外层函数的局部变量(非全局、非内层函数局部) def inner_func(): #内层函数:使用nonlocal修改外层函数的变量 nonlocal nonlocal_num # 声明使用外层嵌套函数的nonlocal_num(不加nonlocal的话,赋值会创建内层局部变量) print(f"\n使用nonlocal前,nonlocal_num:{nonlocal_num}") nonlocal_num += 8 # 修改外层函数的变量 print(f"使用nonlocal后,nonlocal_num为:{nonlocal_num}") inner_func() # 调用内层函数 print(f"外层函数查看nonlocal_num(内层修改后):{nonlocal_num}") test_global() #调用 outer_func() #调用六、匿名函数
基本语法:
函数名 = lambda 形参 :返回值(表达式)
调用: 结果 = 函数名(实参)
举例:
def add(a,b): return a+b print(add(1,2))
===============================
add = lambda a,b : a+b #*a,b就是你们函数的形参,a+b就是返回值的表达式*
print(add(1,2)) #*lambda不需要写return来返回值,表达式本身就是返回*
lambda 的参数形式
函数名 = lambda 形参 :返回值(表达式)
无参数
funa = lambda : "一桶水果茶“
print(funa)
一个参数
funb =lambda name : name
print(funb("Amy"))
默认参数 : 默认参数必须卸载非默认参数后面
func= lambda name,age=18 : (name,age)
print(func("Tom"))
print(func("Tom",20))
关键字参数
fund =lambda **kwargs:kwargs
print(fund(name="Tom",age=18))
可变参数
fune= lambda *args : args
print(func1(1,2,3,4,5))
lambda 结合if 判断
comp = lambda a,b : "a比b小" if a<b else "a比b大" (三目运算)
print(comp(3,2))
特点:
lambda只能实现简单的逻辑,如果逻辑复杂且代码量较大,不建议使用lambda,降低代码的可读性,为后期的代码维护增加困难
七、内置函数
含义:Python已经定义好的函数
查看内置函数:
import builtins
print(dir(builtins)
注意:大写字母开头一般是内置常量名,小写字母开头一般是内置函数名
例如:
之前的类型转换:set()、list()、tuple()
还有以下常见内置函数:
abs() : 返回绝对值 abs(-10)------> 10
sum() : 求和
括号内要放可迭代对象(列表、元组、集合) ,字符串、字典除外
运算时,只要有一个为浮点数,那么结果必定是浮点数
min() : 求最小值
注意:传入了求绝对值函数,则参数就会进行先求绝对值,再取较小者
min(-8,5,key=abs)------> 5
max() :求最大值
zip():将可迭代对象作为参数,将对象中对应的元素打包成一个个元组
如果元素个数不一致,就按照长度最短的返回
两种打印方式:1. 通过for循环 2. 转换成列表打印
注意:必须是可迭代对象
li = [1,2,3,4,5] li1 = ["a","b","c","d"] li2 = [6,7,8,9] print(zip(li,li1,li2)) # <zip object at 0x0000023C02F9A1C0> print(list(zip(li,li1,li2))) # [(1, 'a', 6), (2, 'b', 7), (3, 'c', 8), (4, 'd', 9)] for i in zip(li,li1,li2): print(i) # (1, 'a', 6) # (2, 'b', 7) # (3, 'c', 8) # (4, 'd', 9)map():
含义:可以对可迭代对象中的每一个元素进行映射,分别去执行
格式:map(func,iter1) : func--是自己定义的函数,iter1--迭代对象
简单来说,就是对象中的每一个元素都会去执行这个函数,即传入func函数,并返回一个迭代器。
注意:只要写函数名,不需要加上小括号
li = [1,2,3,4,5] func = lambda x :x*x print(map(func,li)) # <map object at 0x000002184A84D690> print(list(map(func,li))) # [1, 4, 9, 16, 25]reduce():
含义:先把对象中的两个元素取出,计算出一个值然后保存着,接下来把这个计算值跟第三个元素进行计算
格式:需要先导包
from functools import reduce # 函数工具包
reduce(function,sequence) function--函数:必须是两个参数的函数,sequence--序列:可迭代对象
from functools import reduce i = [1,2,3,4] def func(x,y): return x+2*y # 1+2*2=5--->5+2*3=11--->11+2*4=19 print(reduce(func,li)) # 19all() : 判断序列是否全部为真,或者可迭代对象是否为空
注意:all()函数的返回值是一个布尔值,()中应该放置一个可迭代对象。
print(all([1,2,3,4,5])) # True print(all([])) # 空序列为真,True print(all([0,1,2,3,4,5])) # 0为假,Flaseany():判断序列是否至少有一个为真,或者可迭代对象是否为空
注意:any()函数的返回值是一个布尔值,()中应该放置一个可迭代对象。
print(any([1,2,3,4,5])) # True print(any([])) # 空序列为假,Flase print(any([0,1,2,3,4,5])) # 0为假,1为真,2为真,3为真,4为真,5为真,所以返回Trueenumerate() : 把一个序列变成(索引-元素)对,返回一个枚举对象
注意:
enumerate()函数的返回值是一个枚举对象,而不是一个列表,()中应该放置一个可迭代对象。
索引默认从0开始,如果想要从其他数值,可以enumerate([1,2,3],1),此时默认从1开始
for i,j in enumerate([1,2,3]): print(i,j) print(list(enumerate([1,2,3]))) # [(0, 1), (1, 2), (2, 3)] print(tuple(enumerate([1,2,3]))) # ((0, 1), (1, 2), (2, 3)) print(list(enumerate(["a",2,3],1))) # 索引值从1开始,[(1, 'a'), (2, 2), (3, 3) # 0 1 # 1 2 # 2 3 def print_users(*args): """批量打印用户名称""" print("当前在线用户:") for idx, name in enumerate(args, 1): print(f" {idx}. 用户:{name}") # 调用示例 print_users("张三", "李四") # 输出: # 当前在线用户: # 1. 用户:张三 # 2. 用户:李四filter():过滤元素,把函数作用于序列的每一个元素,返回一个迭代对象,返回的迭代对象中只包含函数返回值为真的元素,即取出满足条件的元素
sorted():排序, 对序列进行排序,返回一个迭代对象,从小到大
sorted(可迭代对象,reverse=True) : 反向排序,从大到小
print(list(filter(lambda x:x%2==0,[1,2,3,4,5,6,7,8,9,10]))) #[2, 4, 6, 8, 10] print(list(sorted([3,23,88,4,53,61,7,8,9,10]))) #[3, 4, 7, 8, 9, 10, 23, 53, 61, 88] print(list(sorted([3,23,88,4,53,61,7,8,9,10],reverse=True))) #[88, 61, 53, 23, 10, 9, 8, 7, 4, 3]
八、拆包
含义:对于函数中的多个返回数据,去掉元组,列表或者字典,直接获取里面数据的过程
方法:
基础序列拆包:
针对列表、元组、字符串、生成器等可迭代的序列类型,将元素按位置一一对应赋值给变量
元组内的个数与接收的变量个数相同,对象内有多少个数据就需要定义多少个变量接收
一般在获取元组值的时候使用
tua = (1,2,3,4)
a,b,c,d = tua-------> print(a,b,c,d)-------> 1 2 3 4
a,b = tua------->报错,值错误,要拆包的值过多
扩展拆包(* 处理不定长元素)
使用*符号,用 * 符号接收 “剩余的多个元素”,将其打包成列表,解决 “变量数与元素数不匹配” 的问题
一般在函数调用时使用
用 *_ 接收不需要的元素(_ 是 Python 中约定俗成的 “占位符变量”)
tua = (1,2,3,4)
a,*b = tua------> print(a,b) -----1 [2,3,4]
def funa(a,b,*args): print(a,b,args) funa(1,2,3,4,5,6) # 1 2 (3, 4, 5, 6) arg = (1,2,3,4,5,6) funa(*arg) # 1 2 (3, 4, 5, 6) lst = [100, 200, 300, 400] # 只取第二个元素,其余忽略 _, second, *_ = lst print(second) # 输出:200字典拆包
直接用 ** 拆包:将键值对拆为关键字参数(传给函数)
直接用 * 拆包:仅拆解字典的键(等价于 dict.keys())
d ={"姓名": "Tom", "年龄": 18} name, age = d *arg, = d # 逗号是为了明确告诉 Python:这是一个 “序列解包” 操作,而非单纯的变量赋值 print(name, age) # 姓名 年龄 print(arg) # ['姓名', '年龄'] def func(name, age): print(name, age) info = {"name": "Tom", "age": 20} func(**info) # Tom 20