0.【函数思想】
实现函数要基于高内聚,低耦合的思想。
0.1 函数高内聚
函数内部的代码逻辑和功能彼此相关,实现的是一个具体的功能或目标,各个部分之间密切配合。
一个高内聚的函数通常只完成一个明确的任务,并且其内部的代码逻辑清晰、简洁。
0.2 函数低耦合
函数之间的依赖关系较弱,相对独立,一个函数的改动不会对其他函数造成过多的影响。
低耦合的函数在设计上应该尽量减少使用全局变量或直接修改其他函数的参数,而是通过参数传递和返回值来进行数据交互。
0.3 高内聚低耦合优点
- 可维护性:函数内部的代码高度相关和一致,使得函数更易于理解、调试和修改,减少了不相关的代码耦合。
- 可测试性:函数的高内聚性使得它们更易于独立地进行单元测试,因为它们具有清晰的功能和输入输出。
- 可复用性:函数之间的低耦合性使得它们可以在不同的上下文中被重复使用,提高了代码的复用性。
- 灵活性:函数之间相互独立且功能明确,使得系统更容易进行扩展和修改,不会对其他函数产生很大的影响。
1.函数返回值return
- 默认返回None
- 函数执行到retrun后不继续往下执行
- 可以有多个return(在不同条件下),同一时刻只能返回一个
- 想要一次返回多个值可以直接放在retrun后,用逗号隔开(实际是一个元组)
自动组包解包 https://ceshiren.com/t/topic/30328
2.函数参数
2.1位置参数/必备参数
- 数量必须和定义时一致:抛出 TypeError 异常,提示missing x required positional argument
- 位置必须与定义时一致:抛出 TypeError 异常或者结果与预期不符的情况。
def printMsg(n, msg):
for i in range(n):
print(f'第{i+1}次输出{msg}')
# 正确使用位置参数
printMsg(5, "Hogworts")
# 错误使用位置参数
printMsg("Hogworts", 5)# TypeError: 'str' object cannot be interpreted as an integer
2.2关键字参数
使用形式参数的名字来确定输入的参数值,不再需要与形式参数的位置完全一致,只要将参数名写正确即可。
def printMsg(n, msg):
for i in range(n):
print(f'第{i+1}次输出{msg}')
# 关键字参数
printMsg(n=5, msg="Hogworts")
printMsg(msg="Hogworts", n=5)
2.3默认参数
在定义函数时,形参可以定义变量一样进行赋值,这个值就是默认该参数的默认值。
注意:指定默认值的形式参数必须放在所有未指定默认值参数的后面
def my_power(m, n=2,a=1):
return m ** n + a
# 使用指定的参数--通过位置进行传递
print(my_power(2, 3,2))# 10
# 使用指定的参数--通过参关键字传递
print(my_power(n=2, a=3,m=2))# 7
# 使用默认值参数
print(my_power(2))# 5
# 使用默认参数n,a实际传值
print(my_power(2,a=2))# 6
# n实际传值,使用默认参数a
print(my_power(2,n=3))# 9
2.4可变参数
Python中提供了可变参数的概念用来解决参数个数不确定的的情况
2.4.1 可变位置参数 *args
- args作为形参,接收不确定个数的位置参数(*args将接收到的任意多实际参数放在元组中,元组名是args)
-
*args
:元组内部的值,没有(),类似:1 2 3 。。。; -
args
:完整的元组数据,类似:(1,2,3…); - 也就是:传递给函数之后,
*args
和传递的内容一样,而args
是给传递的值套了个“()”将其转成元组类型;
-
举例:
def fun(*args):
print(args) # 输出:(1, 2, 3)
# 解包
print(*args) # 输出:1 2 3
print(type(args)) # 输出:<class 'tuple'>
for i in args:
print(i)
fun(1,2,3)
2.4.1 可变关键字参数 **kwargs
kwargs作为形参,接收不确定个数的关键字参数(*kwargs将接收到的任意多实际参数放在字典中,字典名kwargs)
举例:
def fun(**kwargs):
print(kwargs) # 输出:{'a': 1, 'b': 2, 'c': 3}
# print(**kwargs) #会报错TypeError: 'a' is an invalid keyword argument for print()
print(*kwargs) #对字典的key解包,结果为: a b c
for k,v in kwargs.items():
print(k,v)
fun(a=1,b=2,c=3)
2.4.3 混合参数
当定义函数时,参数列表中出现了多种类型的参数,定义时需要注意参数的定义顺序,如果顺序使用不正确,在调用函数时,可能会报错。
正确顺序的定义为:位置参数,可变位置参数,默认值参数,可变关键字参数
def fun(name1,*args,age=1,**kwargs):
pass
3 变量作用域
- 变量的作用域决定了在哪一部分程序可以访问哪个特定的变量名称。Python 的作用域一共有4种,分别是:
-
L(Local)
:最内层,包含局部变量,比如一个函数/方法内部。 -
E(Enclosing)
:包含了非局部(non-local)也非全局(non-global)的变量,一般在闭包中出现。 -
G(Global)
:当前脚本的最外层,比如当前模块的全局变量。 -
B(Built-in)
: 包含了内置(内建)的变量/关键字等,最后被搜索。 - 查找规则顺序:
L –> E –> G –> B
。在局部找不到,便会去局部外的局部找(例如闭包),再找不到就会去全局找,再者去内置中找。
-
3.1局部变量
局部变量是指在函数内部定义并使用的变量。
- 它只在函数内部有效,即函数内部的名字只在函数运行时才会创建,在函数运行之前或者运行完毕之后,所有的名字就被销毁都不存在了。
- 如果在函数外部使用函数内部定义的变量,就会抛出 NameError 异常。
3.2全局变量
- 定义在函数外的变量为全局变量,全局变量可以在当前程序文件的任何位置进行访问 。
- 当全局变量和局部变量同名时,根据作用域的查找规则顺序,内部变量会屏蔽全局变量。
全局变量主要有两种情况:
(1)如果一个变量在函数体外定义,那么不仅在函数外可以访问到,在函数内也可以访问到。在函数体以外定义的变量是全局变量。
msg = "学习测试开发来霍格沃兹测试学社"
def var_demo():
print("函数体内全局变量 msg 的值为", msg)
var_demo()
print("函数体外全局变量 msg 的值为", msg)
---------------------------------------------------------------
函数体内全局变量 msg 的值为 学习测试开发来霍格沃兹测试学社
函数体外全局变量 msg 的值为 学习测试开发来霍格沃兹测试学社
(2) 如果一个变量在函数体内定义,并且使用 global 关键字修饰后,该变量也就变为全局变量。在函数体外可以访问该变量,并且在函数体内还可以对其进行修改 。
msg = "学习测试开发来霍格沃兹测试学社" # 创建一个局部变量并赋值
print("函数体外全局变量 msg 的值为", msg) # 在函数体外输出局部变量的值
def var_demo():
global msg
msg = "霍格沃兹测试学社值得信赖" # 此时已经申明了 msg 为全局变量
print("函数体内变量 msg 的值为", msg) # 输出局部变量 msg 的值
var_demo() # 调用函数
print("函数体外全局变量 msg 的值为", msg) # 在函数体外输出局部变量的值
-------------------------------------------------------------------------------------------------------
函数体外全局变量 msg 的值为 学习测试开发来霍格沃兹测试学社
函数体内变量 msg 的值为 霍格沃兹测试学社值得信赖
函数体外全局变量 msg 的值为 霍格沃兹测试学社值得信赖
全局变量和局部变量优缺点:
- 全局变量的优点:
-
- 全局变量在整个程序中都可访问,方便在不同的函数或模块之间共享数据。
-
- 全局变量可以保存程序运行期间的状态,比如计数器或状态标志。
-
- 全局变量的缺点:
-
- 全局变量的作用范围很大,容易被误修改,导致程序出现错误。
-
- 在多个函数中使用同名的全局变量时,很容易出现混淆和命名冲突的问题。
-
- 全局变量的使用不宜过多,因为它们会占用内存资源。如果程序中有太多的全局变量,会增加维护和调试的难度。
-
- 局部变量的优点:
-
- 局部变量的作用范围限于所在的函数或代码块中,不会对其他函数或模块造成影响。这样可以防止变量的误修改或命名冲突。
-
- 局部变量仅在需要时才会被创建和销毁,节省了内存资源。
-
- 局部变量的缺点:
-
- 局部变量的作用范围有限,不能在其定义范围外直接访问。如果需要在多个函数之间共享数据,就不能使用局部变量,需要采用其他的方式来传递数据。
-
- 当函数中定义了较多的局部变量时,可能会使代码显得冗长和难以阅读,增加了编写和维护的复杂性。
-