函数
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的地址值