4.python-定义函数
函数
1. pycharm快捷键
Ctrl + Q 快速查看文档(能快速查看到选择的函数创建者对该函数的注释)
2. 定义
(1) 用于封装一个特定的功能,表示一个功能或者行为。
(2) 函数是可以重复执行的语句块, 可以重复调用。
(3) 设计理念:崇尚小而精,拒绝大而全
""" 函数设计理念: 崇尚小而精,拒绝大而全 返回值 """ # 需求:定义函数,实现2个数字相加 """ def add(): # 获取数据 one = int(input("请输入第一个数字:")) two = int(input("请输入第二个数字:")) # 逻辑计算 result = one + two # 显示结果 print("结果是:%s" % result) add() """ # 函数要细分明确它的功能, # 如逻辑计算,还是获取数据,抑或显示结果,功能要明确 def add(one, two): # 逻辑计算 result = one + two return result # 返回结果 【发送】 # 接收返回值 【接收】 data = add(2, 5) print(data)
3. 作用
将功能的做法与用法分离
提高代码的可重用性和可维护性(代码层次结构更清晰)。
4. 基础语法
4.1 定义函数
(1) 语法
def 函数名(形式参数): 函数体
(2) 说明:
def 关键字:全称是define,意为”定义”。
函数名:对函数体中语句的描述,规则与变量名相同。
形式参数:函数定义者要求调用者提供的信息。
函数体:完成该功能的语句。
""" 函数-参数 函数调用者 传递给 函数定义者 传递的信息 """ # 做法(变化) def attack(count): # 形式参数:抽象的 for i in range(count): # 01234 print("直拳") print("摆拳") print("勾拳") # 调试F8:逐过程执行(跳过函数) # F7:逐语句执行(进入函数) # 用法 count = 2 attack(count) # 实际参数:具体的 循环2次 num = 3 attack(num) # 循环3次 attack(5) # 循环5次
(3) 函数的第一行语句建议使用文档字符串描述函数的功能与参数(可在pycharm中按ctrl+q查看)
""" 练习1:创建计算治愈比例的函数 confirmed = int(input("请输入确诊人数:")) cure = int(input("请输入治愈人数:")) cure_rate = cure / confirmed * 100 print("治愈比例为" + str(cure_rate) + "%") """ def calculate_cure_ratio(confirmed, cure): """ 计算治愈比例的函数 :param confirmed: int类型,确诊人数 :param cure: int类型,治愈人数 :return: float类型,治愈比例 """ cure_rate = cure / confirmed * 100 return cure_rate rate = calculate_cure_ratio(58, 57) print(rate) num01, num02 = 58, 57 calculate_cure_ratio(num01, num02) print("治愈比例为%s" % rate)
4.2 调用函数
(1) 语法:函数名(实际参数)
(2) 说明:根据形参传递内容。
4.3 返回值
(1) 定义: 函数定义者告诉调用者的结果。
(2) 语法: return 数据
(3) 说明:
return后没有语句,相当于返回 None。
函数体没有return,相当于返回None。
""" 函数 - 返回值语法 """ # 返回结果 def func01(): print("func01执行了") return 100 def func02(): print("func02执行了") # 函数没有返回值,相当于返回了None # return # 函数有返回,但没值 def func03(): # 正常:3个循环应该有3个break结束 # while True: # while True: # while True: # break # break # break while True: while True: while True: return # 退出函数 # 接收结果 data01 = func01() print(data01) # 也可以不接 func01() data02 = func02() # None print(data02)
5. 可变/不可变类型在传参时的区别
""" (1) 不可变类型参数有: 数值型(整数,浮点数) 布尔值bool None 空值 字符串str 元组tuple """ def func01(p1, p2, p3): p1 += 1 p2 += "world" p3 += (4, 5) number01 = 10 str01 = "hello" tuple01 = (1, 2, 3) func01(number01, str01, tuple01) print(number01) # 10 print(str01) # "hello" print(tuple01) # (1, 2, 3) """ (2) 可变类型参数有: 列表 list 字典 dict """ def func02(p1, p2): p1[0] += 1 p1[1] += "world" p2["num_tuple"] += (4, 5) list01 = [10, "hello"] dict01 = { "num_tuple": (1, 2, 3) } func02(list01, dict01) print(list01) # [11, 'helloworld'] print(dict01) # {'num_tuple': (1, 2, 3, 4, 5)} """ (3) 结论: 不可变类型的数据传参时,函数内部不会改变原数据的值。 可变类型的数据传参时,函数内部可以改变原数据。 """
6. 函数参数
6.1 实参与形参
def func01(p1, p2, p3): # p1,p2,p3 为形参 print(p1) print(p2) print(p3) data01 = 10 data02 = 20 data03 = 30 # 函数调用时传入的data01,data02,data03为实参 # 按位置顺序与形参一一对应,不能多传或者少传 # data01与p1,data02与p2,data03与p3 func01(data01, data02, data03) # 依次打印10 20 30 # 关键字实参 # 按照名称与形参对应 func01(p3=300, p1=100, p2=200) # 依次打印100 200 300 def func02(a1=1, a2="hello world", a3=False): # 在形参中设置值,为默认形参 print(a1) print(a2) print(a3) # 设置有默认形参可以不传入参数,使用默认数值 func02() # 依次打印1 hello world False # 设置有默认形参传入参数,使用传入的数值 func02(2, "HELLO WORLD", True) # 依次打印2 HELLO WORLD True # 设置有默认形参的情况下可以域关键字实参配合,跳过前面的参数设置 func02(a2="跳过参数1") # 依次打印1 跳过参数1 False
6.2 参数类型注释
# python3.6以后增加的类型标注(注释) # 作用: # 1. 增加代码可读性(知道了变量类型) # 2. 增加类型检测 # 语法: # 1. 参数: 变量:类型 # 2. 返回值: def 函数名()->类型: # 3. 选择多种类型: 类型|类型 def func01(p1: int, p2: str, p3: bool): # 分别为形参p1注释int类型,形参p2注释str类型,形参p3注释bool类型 print(p1) print(p2) print(p3) func01(1, "hello", False) # 使用参数类型注释,传入实参时编译器会提示类型 func01("hello", 33, 6.666) # 传入与参数注释类型不同的实参,不会强制报错,在编译器中会高亮显示,提醒类型不符 def func02(a1=3, a2="world"): # 设置默认形参,也能达到参数注释的效果 print(a1) print(a2) func02(33, "cool") def func03() -> int: # 为返回值添加类型注释 data01 = 111 return data01 # 返回的值与注释的类型不同时,,编译器会高亮显示,不会报错 num = func03() # 有返回值注释,在接收返回值时,编译器会有类型提示
7. 作用域
7.1 定义
变量起作用的范围。
7.2 分类
# Local局部作用域:函数内部。 # Global全局作用域:模块(.py文件)内部。 data01 = 10 # 全局变量在整个文件中都适用 def func01(): data02 = 20 # 局部变量,只在当前函数的作用域中有效 print(data01) # 函数内部能使用全局变量 10 func01() # print(data02) # 运行会报错,函数作用域外无法使用函数内的局部变量data02 # 变量名的查找规则 # 在访问变量时,先查找局部变量,之后是全局变量。 data03 = 30 def func02(): data03 = 300 print(data03) # 300 变量同名时函数内会优先使用函数内部的局部变量data03 func02() # 结论 # 局部变量 # (1) 定义在函数内部的变量(形参也是局部变量) # (2) 只能在函数内部使用 # (3) 调用函数时才被创建,函数结束后自动销毁 # 全局变量 # (1) 定义在函数外部,模块内部的变量。 # (2) 在整个模块(py文件)范围内访问(但函数内不能将其直接赋值)。 # 关键字 global # (1) 作用: # 在函数内部修改全局变量。 # 在函数内部定义全局变量(全局声明)。 # (2) 语法: # global 变量1, 变量2, … # (3) 说明 # 在函数内直接为全局变量赋值,视为创建新的局部变量。 # 不能先声明局部的变量,再用global声明为全局变量。 data04 = 40 data05 = 50 data06 = 60 def func03(): global data04, data05 # 使用global将data04和data05标记为全局变量,可以直接在函数内修改它 data04 += 400 data05 *= 5 data06 = 600 func03() print(data04) # 440 global标记后在函数中修改 print(data05) # 250 global标记后在函数中修改 print(data06) # 60 没有被修改
函数的内存分别
程序自上而下运行,会将函数add加载到代码区
将int类型10赋值给num01,num01存储的是10的地址值
调用函数add,传入参数num01和20,则参数p1存储10的地址值,p2存储20的地址值
将p1+p2赋值给result,result存储的是p1+p2结果30的地址值
函数最后返回result被赋值给data,因此data存储的是30的地址值.函数运行完毕其内存被释放.
程序自上而下运行,将函数calculate_iq_level加载到代码区
调用函数calculate_iq_level传入18和15,则ma存储的是18地址值,ca存储的是15的地址值
将ma/ca*100赋值给iq,iq存储的是ma/ca*100结果120的地址值
函数最后返回字符串"超常"赋值给level,level存储的是"超常"的地址值,函数运行结束在内存中被释放
程序自上而下运行将函数func01加载到代码区
将int类型10赋值给num,num存储的是10的地址值
将列表[10]赋值给list01,list01存储的是列表[10]的地址值
运行函数func01传入num和list01,则p1存储的是10的地址值,p2存储的是[10]的地址值
将int类型20赋值给p1,p1存储的是20的地址值
将int类型20赋值给p2[0],则p2[0]存储的是20的地址值,函数运行结束在内存中被释放
num在函数中没有被修改,list01在函数中list01[0]存储的地址值被修改为20的地址值
程序自上而下的运行,将函数func01加载到代码区
将列表[10]赋值给a,a存储的是[10]的地址值
将列表[20]赋值给b,b存储的是[20]的地址值
运行函数func01传入a[:]和b,则p1存储的是新列表[10](为原先列表复制)的地址值,p2存储的是列表[20]的地址值
将100赋值给p1[0],p1[0]存储的是100的地址值
将[200]赋值给p2[:],p2[0]存储的是200的地址值,函数运行结束,在内存中被释放
a在func01运行过程中没有被修改,存储的还是[10]地址值,b在func01运行过程中被修改,原先存储的地址值不变,b[0]存储的地址值发送改变
将int类型10赋值给data01,data01存储的是10的地址值
将函数func01加载到代码区中
将int类型10赋值给data02,data02存储的是10的地址值
运行函数func01传入data02,p1存储的是10的地址值
使用关键字global标记函数内的data01为全局变量,则data01 += 1,全局变量data01存储的是11的地址值,p += 1存储的是11的地址值
函数运行结束,在内存中被释放,变量p也不存在了,变量data02没有改变,在函数中使用关键字global标记了data01,并做了修改,data01变为存储11的地址值
使用关键字global标记函数内的data01为全局变量,则data01 += 1,全局变量data01存储的是12的地址值,p += 1存储的是11的地址值
函数运行结束,在内存中被释放,变量p也不存在了,变量data02没有改变,在函数中使用关键字global标记了data01,并做了修改,data01变为存储12的地址值
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 分享一个免费、快速、无限量使用的满血 DeepSeek R1 模型,支持深度思考和联网搜索!
· 基于 Docker 搭建 FRP 内网穿透开源项目(很简单哒)
· ollama系列01:轻松3步本地部署deepseek,普通电脑可用
· 25岁的心里话
· 按钮权限的设计及实现