1、函数
1.1、定义
- 函数用于封装一个特定的功能,表示一个功能或者行为
- 函数是可以重复执行的语句块, 可以重复调用
1.2、作用
提高代码的可重用性和可维护性(代码层次结构更清晰)
1.3、定义函数
- 语法:
def 函数名(形式参数):
函数体
-
说明:
- def 关键字:全称是define,意为”定义”
- 函数名:对函数体中语句的描述,规则与变量名相同
- 形式参数:方法定义者要求调用者提供的信息
- 函数体:完成该功能的语句
- 函数的第一行语句建议使用文档字符串描述函数的功能与参数
-
示例
# 定义一个行列转换函数 def row_col_recover(list): """ 获取 list 中的数据进行行列转换\n :param list: 需要转换的数据列表 :return:返回转换后的数据 """ temp = [] for c in range(len(list[0])): temp.append([]) for r in range(len(list)): temp[c].append(list[r][c]) return temp
1.4、调用函数
-
语法
-
函数名()
-
变量 = 函数名(实际参数)
-
-
说明
根据形参传递内容 -
示例
# 没有返回值函数调用 row_col_recover() # 有返回值函数调用 recover_list = row_col_recover(list)
1.5、返回值
- 定义
方法定义者告诉调用者的结果 - 语法:
return 数据 - 作用
- 返回数据
- 退出函数
- 说明
- return后没有语句,相当于返回 None
- 函数体没有return,相当于返回 None
1.6、可变/不可变类型在传参时的区别
- 不可变类型参数有
- 数值型(整数,浮点数,复数)
- 布尔值( bool)
- 空值 (None )
- 字符串 (str)
- 元组 (tuple)
- 固定集合 (frozenset)
- 可变类型参数有
- 列表 (list)
- 字典 (dict)
- 集合 (set)
- 传参说明
- 不可变类型的数据传参时,函数内部不会改变原数据的值
- 可变类型的数据传参时,函数内部可以改变原数据, 函数执行过后,不用通过返回值也能拿到修改后的结果
1.7、函数参数
1.7.1、实参传递方式(argument)
-
位置传参
实参与形参的位置依次对应 -
序列传参
实参用*将序列拆解后与形参的位置依次对应 -
关键字传参
实参根据形参的名字进行对应 -
字典关键字传参
- 定义
实参用**将字典拆解后与形参的名字进行对应 - 作用:
配合形参的缺省参数,可以使调用者随意传参
- 定义
-
示例
def fun01(a, b, c): print(a) print(b) print(c) # 位置实参:实参根据位置与形参进行对应 fun01(1, 2, 3) # 序列实参:使用星号将序列中的元素拆开,与形参进行对应 # 序列:字符串、列表、元组 list01 = ["aaa", "bb", "cc"] fun01(*list01) # 关键字实参:实参根据名称与形参进行对应 fun01(b=2, a=1, c=3) # 字典实参:使用双星号将字典中的元素拆开,根据“键”与形参进行对应,传递值 dict01 = {"c": 33, "a": 11, "b": 22} fun01(**dict01)
1.7.2、形参定义方式(parameter)
-
缺省参数
- 语法
def 函数名(形参名1=默认实参1, 形参名2=默认实参2, ...): 函数体
- 说明
- 缺省参数必须自右向左依次存在,如果一个参数有缺省参数,则其右侧的所有参数都必须有缺省参数
- 缺省参数可以有0个或多个,甚至全部都有缺省参数
-
位置形参
- 语法
def 函数名(形参名1, 形参名2, ...): 函数体
-
星号元组形参
- 语法
def 函数名(*元组形参名): 函数体
- 作用
收集多余的位置传参 - 说明
- 一般命名为'args'
- 形参列表中最多只能有一个
-
命名关键字形参
- 语法
def 函数名(\*, 命名关键字形参1, 命名关键字形参2, ...): 函数体 def 函数名(\*args, 命名关键字形参1, 命名关键字形参2, ...): 函数体
- 作用
强制实参使用关键字传参
-
双星号字典形参
- 语法
def 函数名(\*\*字典形参名): 函数体
- 作用:
收集多余的关键字传参 - 说明:
- 一般命名为'kwargs'
- 形参列表中最多只能有一个
-
参数自左向右的顺序
位置形参 --> 星号元组形参 --> 命名关键字形参 --> 双星号字典形参 -
示例
# 默认形参:实参可以不传递数据(从右向左依次存在) def fun01(a=0, b="bb", c=1.5): print(a) print(b) print(c) fun01() fun01(1, "b") # 位置形参:实参根据位置与形参进行对应 def fun01(a,b,c): print(a) print(b) print(c) fun01(1,2,3) # 星号元组形参:让位置实参的数量无限 def fun02(p1, p2, *args): print(args) fun02(1, 2) fun02(1, 2, 3) fun02(1, 2, 3, 4, 5) # 命名关键字形参:传递的实参必须是关键字实参 ## 写法1:星号元组形参以后的参数是命名关键字形参 def fun03(*args, p1="", p2): print(args) print(p1) print(p2) fun03(2, 2, p1=111, p2=222) fun03(p1=111, p2=222) fun03(p2=222) ## 写法2:星号以后的位置形参是命名关键字形参 def fun04(*, p1=0, p2): print(p1, p2) fun04(p1=1, p2=2) fun04(p2=2) # 双星号字典形参:让关键字实参的数量无限 def fun05(**kwargs): print(kwargs) fun05(a=1) # 相当于{'a': 1} fun05(a=1, b=2) fun05(a=1, b=2, c=3) # 相当于{'a': 1, 'b': 2, 'c': 3}
2、作用域LEGB
- 作用域:变量起作用的范围
- Local局部作用域:函数内部,函数内部的变量称为局部变量
- Enclosing外部嵌套作用域 :函数嵌套
- Global全局作用域:模块(.py文件)内部
- Builtin内置模块作用域:builtins.py文件
2.1、变量名的查找规则
- 由内到外:L -> E -> G -> B
- 在访问变量时,先查找本地变量,然后是包裹此函数外部的函数内部的变量,之后是全局变量,最后是内置变量
2.2、局部变量
- 定义在函数内部的变量(形参也是局部变量)
- 只能在函数内部使用
- 调用函数时才被创建,函数结束后自动销毁
2.3、全局变量
- 定义在函数外部,模块内部的变量
- 在整个模块(py文件)范围内访问(但函数内不能将其直接赋值)
2.4、global 语句
- 作用
- 在函数内部修改全局变量
- 在函数内部定义全局变量(全局声明)
- 语法
global 变量1, 变量2, … - 说明
- 在函数内直接为全局变量赋值,视为创建新的局部变量
- 不能先声明局部的变量,再用global声明为全局变量
2.5、nonlocal 语句
- 作用
在内层函数修改外层嵌套函数内的变量 - 语法
nonlocal 变量名1,变量名2, ... - 说明
在被嵌套的内函数中进行使用