📔 Python函数 学习笔记
1. 函数概述
1.1 为什么需要函数?
为了解决代码存在的一些问题:
- 组织结构不清晰,可读性较差
- 代码会冗余
- 可维护性差,可扩展性差。
- 程序的模块管理差
- 代码重复率高
所以在一定程度上,函数就是通过封装,让代码可重复利用提高,保持程序的模块性,也让代码块符合单一性的原则
1.2 函数定义语法介绍
| def 函数名(参数列表): # 参数可有可无
"""文档描述"""
函数体
return 值 # return可有可无
|
语法解释:
def:定义函数的关键字
函数名:函数名指向函数内存地址,是对函数体代码的引用。函数的命名可以反映出函数的功能
括号:括号内定义参数,参数可有可无,且无需指定参数的类型
冒号:括号后面要加冒号。然后在下一行开始缩进编写函数体的代码
"""文档描述""":描述函数功能,参数介绍等信息的文档。非必要,但是建议加上,从而增强函数的可读性。【一般在开源软件中详细,其余情况可写可不写】
- 函数体:由语句和表达式组成
return 值:定义函数的返回值,return 是可有可无。
1.3 函数定义三种形式及其应用场景
| # 方式1 :无参函数的定义
def print_log():
print("Hello World")
print_log() # 函数调用
# 定义函数不会执行函数体代码,但是会检测函数体语法
x = 111
def foo(): # 函数名字不加括号,则打印函数的内存地址(函数名即可获取函数的地址)
print(x)
print("function foo()")
# 方式2 :有参函数的定义
x = 3
y = 7
def operation(x,y):
print("x + y = ",x+y)
print("x - y = ",x-y)
print("x * y = ",x*y)
print("x / y = ",x/y)
operation() # 调用函数
# 方式3:空函数,函数体代码为pass
def func(x,y):
pass
|
1.4 函数调用三种形式及其应用场景
| # 方式1 直接调用函数,只加括号进行调用函数
func()
# 方式2 表达式形式(数学表达式)
res = operation(x,y)
# 方式3 函数调用可以当做参数(函数内嵌套其它函数)
|
1.5 函数返回值三种形式及其应用场景
return 是函数结束的标志
- 即函数体代码一旦运行到return就会立即终止函数的执行。并且会将return后的值当作本次运行的结果返回
| # 返回None:函数体内没有return
def func01():
pass # 函数返回为None
return None # 也是会直接返回值None
# 函数返回一个值:return 值
def func02():
return 10
# 返回多个值:用逗号分隔开多个值,会被return返回成元组
def func03():
return 10,'aaa',[1,2] # 返回后的值格式为元组
|
2. 参数相关概念和分类
2.1 形参和实参
- 形参:在定义函数阶段定义的参数称为形式参数。简称形参,相当于变量名。
- 实参:在调用函数阶段传入的值称为实际参数。简称实参数,相当于变量值。
形参与实参之间的关系:
- 在调用阶段,实参(变量值)会绑定给形参(变量名)
- 绑定关系只能在函数体内使用。
- 绑定关系在函数调用时生效,函数调用结束后接触绑定关系。
实参的形式:
| # 方式1
func(1,2)
# 方式2
a = 1
b = 2
func(a,b)
# 方式3
func(int('1'),2)
func(func1(1,2,3),func2(1,2,3),4)
|
2.2 位置参数
2.3 关键字参数
2.4 默认形参
-
在定义函数阶段,就已经被赋值的形参,称之为 默认参数。
-
特点:在定义阶段就已经赋值,意味着在调用阶段可以不进行赋值操作。
| def func(x,y = 3):
print(x,y)
func(x = 1,y = 4) # 如果要传值,则以传值为主
|
-
如果位置形参和默认形参混合使用,位置形参 必须在 默认形参的 左边
-
默认参数的值是在函数定义阶段被赋值的。
2.5 可变长参数(* 和 ** 的用法)
-
可变长度指的是在调用函数时,传入的值(实参)的个数不固定。
-
实参是用来为形参赋值的,所以对应性针对溢出的实参必须有对应的形参来接收。
-
可变长度的位置参数
| # 使用形式:*形参名:用来接收溢出的位置实参
# 溢出的位置实参会被 * 保存成元组的格式,然后赋值紧跟其后的形参。
# * 后面可以使用任意名字,但是规范上来说,一般是使用 args。格式为:*args
def func(x,y,*z):
print(x,y,z)
func(1,2,3,4,5,6) # x = 1,y = 2,z=(3,4,5,6)
# 对 *内的值进行传值
def mysum(*args): # 参数规范
res = 0
for i in x:
re += i
return res
res = mysum(1,2,3,4,5)
print(res)
|
-
可变长度的关键字参数
| # **形参名:用来接收溢出的关键字实参数。** 会将溢出的关键字实参保存成字典格式,然后赋值给紧跟其后的形参
# ** 后可以紧跟任意名字,但规范一般是使用kwagrs,格式:**kwargs
def func(x,y,**kwargs):
print(x,y,kwargs)
func(1,y = 2,a = 1,b = 3,c = 4)
|
-
如果 * 在实参中,实参中带 *,会先将 * 后的值拆分成位置实参。
| def func(x,y,z):
print(x,y,z)
func(*[1,2,3])
|
-
如果是形参和实参都包含 *,会直接将实参的值拆分,然后再进行赋值操作。
| def func(x,y,*args): # args = (3,4,5,6) 存储成元组的形式
print(x,y,args)
func(1,2,*[3,4,5,6]) # 会拆分值
|
-
** 可以用在实参中(** 后只能使用字典格式),在实参中带 **,先将 ** 后的值得拆分成为位置实参。
| def func(x,y,z):
print(x,y,z)
func(**{'x':1,'y':2,'z':3}) # func(x = 1,y = 2,z = 3)
|
-
形参和实参中都包含 **
| def func(x,y,**kwargs):
print(x,y,z)
func(**{'x':1,'y':2,'a':3,'b':4}) # func(x = 1,y = 2,z = 3)
|
-
如果是 * 和 ** 混合使用
| def func(*args,**kwargs): # 后续传什么值都可以,也为后续参数的扩展留有余地
print(args)
print(kwargs)
|
-
命名关键字参数(了解)
- 在定义函数时, * 后定义的参数,称为命名关键字参数。
| def func(x,y,*args,a,b): # 使用 * 和 *args 是一样的,a和b是命名关键字参数,所以传值时使用关键字方式传
print(x,y)
print(a,b)
# 主要特点:命名关键字实参必须按照 key=value 的形式为其传值。
#
|
3. 生命周期
3.1 名称空间
名称空间:存放变量名字的地方。
3.2 变量作用域
变量的作用域决定了程序可以访问某个特定的变量名称。常见的两种变量作用域:
-
全局变量
- 内置名称看见、全局名称空间。
- 程序内有效,可以被所有的函数共享。
-
局部变量
具体的实例分析:
| # 如果在局部想要修改全局的名字对应的值(不可变类型),需要使用global
def func():
global x # 可以通过global将全局变量的值,在函数内将其修改为局部变量的值
x = 22
func()
print(x) # 打印x
|
nonlocal(了解):修改函数外层函数包含的名字对应的值(不可变类型)
| x = 0
def f1():
x = 11
def f2():
nonlocal x
x = 22
f2()
print("f1 内的x:",x)
f1()
|
4. 函数对象
| # func 就是内存地址
def func():
print("from func")
# 可以当函数的参数传给另一个函数
def foo(x):
x()
#print(x)
foo(func) # 传func的内存地址
# 可以当作函数另外一个函数的返回值
# 可以当作容器类型的一个元素
# 具体实例
def login():
print("登陆成功")
def transfer():
print("转账成功")
def check_balance():
print("查看余额")
def register():
print("注册成功")
# 使用一个字典来存储函数对象,使得代码的可扩展性很强
func_dict = {
'1':login,
'2':transfer,
'3':check_balance,
'4':register
}
# 优化后的字典
func_dict = {
'0':['退出',None],
'1':['登陆',login],
'2':['转账',transfer],
'3':['查询余额',check_balance],
'4':['注册',register]
}
while True:
# 直接优化下面的代码,使用for循环来进行替代
print("""
0 退出
1 登陆
2 转账
3 查看余额
4 注册
""")
# 优化后的代码为
for k in func_dict:
print(k,func_dict[k][0]) #选择
choice = input("请输入操作编号:").strip()
if not choice.isdigit():
print("请输入数字编号")
continue
if choice == '0':
break
if choice in func_dict:
func_dict[choice]()
|
5. 参考资料
- Python官方文档
- W3CSchool Python教程
- 路飞学城Python开发视频课:B站