当我们在不同地方,都需要使用同一个功能时,如果每次都写一遍该功能的代码,显然不仅使我们的代码冗余,还不好对该功能进行修改,而这个时候使用函数则可以方便的解决该问题。
目录
2、使用nonlocal,让在函数嵌套时,内部函数能修改外部函数的变量
前言
在 Python 中,函数就是一堆可以完成某些工作的代码,需要的时候就去调用该代码,用于执行特定任务或计算。通过函数,您可以将代码模块化,提高代码的可读性和可维护性。
正文
一、函数的定义 检测函数体的代码,不会直接执行
def 函数名(形参列表):
函数体代码
return
def func():
print('函数体代码')
二、函数的调用 使用函数体中的代码
函数名(实参列表)
def func():
print('函数体代码')
func() # 调用函数,执行函数体中的代码,输出:函数体代码
print(func) # 输出函数名,拿到的是函数的地址 输出: <function func at 0x000001600ADA4700>
三、形参与实参
1、形参:形式参数 在函数定义阶段时使用的参数 变量名
只在函数中生效(局部变量)
2、实参:实际参数 在函数调用时传入的值 变量值
实参可以是任意数据类型,可以是变量或者表达式
def func(a, b): # 形参会接受函数中对应的位置的值,即a=num1,b=num2;a,b在该函数中可以当变量使用
print(f'{a}+{b}=', a+b, sep='') # 23+14=37
num1 = 23
num2 = 12
func(num1, num2+2) # 实参num1,num2在调用函数时,函数会将实参对应传递给形参
四、函数参数传递的五种形式
1、位置参数(必备参数)
特点:必须传值,按照顺序依次传递给形参
def func(a, b): # 位置参数,按位置给形参传值
print(f'a={a},b={b}')
func(12, 14) # 调用结果为 输出:a=12,b=14
func() # 如果不传值会报错 TypeError: func() missing 2 required positional arguments: 'a' and 'b'
2、默认参数
特点:为形参设定默认值,若不传递参数,则使用默认参数
def func(a=3, b=2): # 默认参数,不传递值则使用默认值
print(f'a={a},b={b}')
func() # 调用结果 输出:a=3,b=2
func(12, 13) # 调用结果 输出:a=12,b=13
3、可变长参数
特点:函数可以接受任意的参数数量,并将其打包成一个元组
def func(*args): # 可变长参数,可以接受任意个实参,并将其打包成一个元组
print(f'args={args}')
func() # 调用结果 输出:args=()
func(12, 13, 12, 13, {1: 2}) # 调用结果 输出:ages=(12, 13, 12, 13, {1: 2})
4、关键字参数
特点:使用关键字进行传递参数,可以不按照位置顺序传递参数
def func(a, b): # 关键字参数,指定实参值传递给形参
print(f'a={a}, b={b}')
func(b=2, a=3) # 调用时形参的位置可以任意放置,调用结果 输出:a=3, b=2
5、可变长关键字参数
特点:可以接受任意数量的关键字参数,并将其打包成一个字典
def func(**kwargs): # 可变长关键字参数,可以接受任意的关键字参数,并将其打包成字典
print(f'kwargs={kwargs}')
func(b=2, a=3, num=2, c='d', d='写代码也摆烂') # 调用结果 输出:kwargs={'b': 2, 'a': 3, 'num': 2, 'c': 'd', 'd': '写代码也摆烂'}
总结:
传入的实参固定的个数:必备参数 关键字参数 默认参数
传入的实参不固定,也不知道有多少:可变长参数和可变长关键字参数
五、pass与return
1、pass占位符
pass
是一个空语句,它的作用是占位符,用于指示代码块为空,即不执行任何操作。只是为了保持代码的结构完整性,同时方便日后的扩展和修改。在判断、循环、异常、类中都可以使用。
# 当我们需要写多个函数来完成代码时,
# 可以利用pass来写出我们函数的大纲,并且可以直接运行,但是不进行任何操作
def add(): # 加
pass # pass 为了确保程序正常运行,先使用pass占位,方便后续编写函数
def sub(): # 减
pass
def multiplication() # 乘法
pass
2、return返回值
return 语句用于从函数中返回一个值,并结束函数的执行。当函数执行到 return 语句时,它会立即停止执行并返回指定的值给调用方。
return主要有两个作用:
1、将函数中的值以函数的调用结果返回,没有返回值,函数的调用结果为None。
2、终止函数的执行,在函数中如果遇见retrun会直接中断函数。
# 1、返回函数中的值
def add(*args):
s = 0
for i in args:
s += i
return s # 将s当作函数add的返回值
a = add(12, 3, 4) # 将函数的返回值赋给a
print(a) # 输出:19
print(add(4, 6, 2)) # 直接输出函数的返回值 输出:12
# 返回多个值
def info():
return '写代码也摆烂', 18 # 返回多个值
print(info()) # 以元组形式返回 输出:('写代码也摆烂', 18)
# 输出空函数
def kong():
pass
print(kong()) # 没有return函数输出函数为None 输出:None
# 2、终止函数的运行
def func(*args):
if args == ():
return False # 如果args时一个空元组则返回False
return True # 如果args不是一个空元组,则if不成立会往后运行,则返回True
print(func()) # False
print(func(1)) # True
六、变量的作用域
1、全局作用域
在模块顶层(即非函数内部)定义的变量具有全局作用域,可以在整个模块中的任何地方访问,程序运行结束时销毁。但是不能在函数中对其进行修改。
a = 4 # 定义全局变量a
def func1():
print(a) # 输出全局变量
def func2():
a = 19 # 无法修改全局变量的值,这里的a会被当成是函数func2中的局部变量
print(a) # 输出func2中的局部变量a的值19,不影响全局变量a的值
print(a) # 输出全局变量a 输出:4
func1() # 调用结果 输出:4
func2() # 调用结果 输出:19
print(a) # 调用func2 后全局变量a的值未修改 输出 4
a = 11 # 在函数外部,与全局变量同级可以修改全局变量
print(a) # 输出 11
func1() # 调用结果 输出:11
2、局部作用域
在函数内部定义的变量具有局部作用域,只能在定义它们的函数内部访问。局部变量在函数被调用时创建,在函数执行完毕后销毁。
def func():
a = 12 # 定义局部变量a,只能在函数func中使用,函数执行结束时销毁
print(a) # 输出12
func() # 调用输出:12
print(a) # 无法访问函数func中的变量a,会直接报错 NameError: name 'a' is not defined
3、嵌套作用域(了解)
在一个函数内部定义的函数可以访问外部函数的变量,但不能修改它们的值。外部函数不能访问内部函数的变量。
def out():
a = 12 # out函数中的局部变量
def inner1():
print(a) # 可以在out函数的内部函数中使用输出:12
def inner2():
a = 1 # 但是不能对其修改,这里就和全局变量在函数内一样,变成了inner2的局部变量
c = 12
print(a) # 输出inner2中的局部变量a 输出:1
inner1()
inner2()
print(a) # 输出out中的局部变量a,输出:12
print(c) # 在函数内部的函数中定义的变量也不能拿出来使用会直接报错 NameError: name 'c' is not defined
out()
七、 修改变量的作用域
1、使用global,让全局变量能在函数中修改
在函数内部,通过使用 global
关键字声明一个变量,可以将该变量标记为全局变量,从而使得在函数内部对该变量的修改能够影响到全局作用域中的变量。
a = 10
b = 12
def func():
global a # 声明a为全局变量
a = 1 # 对全局变量进行赋值
b = 2 # 未声明为全局变量,直接赋值会创建一个新的局部变量名为b,不影响全局变量b
print(a, b) # 输出a(全局变量),b(局部变量) 结果为:1,2
print(a, b) # 输出全局变量a,b 结果为:10,12
func() # 调用函数
# 全局变量a在func函数中被修改了,但是b没有
print(a, b) # 输出全局变量a,b 结果为:1,12
2、使用nonlocal,让在函数嵌套时,内部函数能修改外部函数的变量
在嵌套函数中,通过使用 nonlocal
关键字声明一个变量,可以将该变量标记为非局部变量,从而使得在内部函数中对该变量的修改能够影响到外部函数的作用域。
def out():
a = 12 # out函数中的局部变量
def inner1():
a = 13
print(a) # 直接给a赋值,会重新在inner1中创建一个新的a变量,不会修改out函数中的局部变量a
def inner2():
nonlocal a # 声明其不是inner2中的局部变量,则程序会往外层函数找变量a
a = 1 # 此时修改的是out函数的局部变量a
print(a) # 输出inner2中的局部变量a 输出:1
print(a) # 输出:12
inner1() # 调用结果为输出:13
print(a) # 在inner2修改之前 输出:12
inner2() # 调用结果为输出:1
print(a) # out中的局部变量a,输出:1 因为在inner2函数中被修改了所以是1
out()
需要注意的是,过度使用 global
和 nonlocal
可能会导致代码变得难以理解和维护,因为它们引入了作用域之间的耦合关系。因此,在修改变量的作用域时,建议仔细考虑代码的结构,并尽量避免过度依赖于这些关键字。
总结
函数的五种传参形式,融会贯通之后很方便,用来设计功能。
欢迎指正!