函数的定义与调用:使用def关键字来定义
- 语法格式:
# 函数的定义
def 函数名 ([参数列表]): #[参数列表]可以包含一个或多个参数也可以为空
函数体 # 实现函数功能的具体代码
return # 可忽略
# 函数的调用
函数名([参数列表])
计算两个数之和的函数:
# 无参函数
def add():
result = 11 + 22
print(result)
add()
# 有参函数
def add_modify(a,b):
result = a + b
print(result)
add(11,12)# 输入变量的具体值
- 函数的嵌套调用:在定义的函数内可调用函数的内置函数
函数参数的传递:
- 参数的分类
形式参数 | 定义函数时设置的参数 |
实际参数 | 调用函数时传入的参数 |
- 参数传递:位置参数传递、关键字参数传递、默认参数传递、参数的打包与解包以及混合传递。
1、位置参数的传递 :
函数在被调用时会将实参按照相应的位置依次传递给形参,也就是说将第一个实参传递给第一个形参,将第二个实参传递给第二个形参,以此类推。
# 比较a与b的大小
def get_max(a,b):# 定义函数
if a > b:
print(a,"是较大的值!")
else:
print(b,"是较大的值!")
get_max(10,5) #将10传递给a,5传递给b
结果如下:
10 是较大的值!
2、关键字参数的传递:
通过“形参=实参”的格式将实参与形参相关联,将实参按照相应的关键字传递给形参。
def connect(ip, port):
print(f"设备{ip}:{port}连接!")
connect(ip="127.0.0.1", port=8080) # 利用关键字对参数进行传递
结果如下:
设备127.0.0.1:8080连接!
3、默认参数的传递:
在定义函数时对形参进行默认值定义,若在调用时没有给被定义默认值的参数传值则直接打印默认值,否则打印传入的值。
def connect(ip, port=8080): # 指定port的默认值为8080
print(f"设备{ip}:{port}连接!")
connect(ip="127.0.0.1") # 不给带有默认值的形参传值
connect(ip="127.0.0.1", port=3306) # 给带有默认值的形式传值
结果如下:
设备127.0.0.1:8080连接!
设备127.0.0.1:3306连接!
4、函数的打包与解包:
- 注:在函数定义时, * 表示打包,在函数体内部, * 表示的却是解包。
(1)打包:函数在定义时无法确定需要接收多少个数据,那么可以在定义函数时为形参添加“*”或“**”。
* 打包:接受以元组形式打包的多个值。
def test(*args):
print(args)
test(11, 22, 33, 44, 55) # 传入多个数据并调用
结果如下:
(11, 22, 33, 44, 55)
**打包:接收以字典形式打包的多个值。
def test(**kwargs):
print(kwargs)
test(a=11, b=22, c=33, d=44, e=55) # 传入字典的key值以及value值
结果如下:
{'a': 11, 'b': 22, 'c': 33, 'd': 44, 'e': 55}
- 若函数没有接收到任何数据,参数*args和**kwargs为空,即它们为空元组或空字典。
(2)解包:实参是元组 时可以使用“*”拆分成多个值,按位置参数传给形参。实参是字典时可以使用“**” 拆分成多个键值对,按关键字参数传给形参。
* 解包:解包实参是元组的参数。
def test(a, b, c, d, e):
print(a, b, c, d, e)
nums = (11, 22, 33, 44, 55)
test(*nums) # 以元组的形式解包参数
结果如下:
(11,22,33,44,55)
**解包:解包实参是字典的参数。
def test(a, b, c, d, e):
print(a, b, c, d, e)
nums = {"a":11, "b":22, "c":33, "d":44, "e":55}
test(**nums) # 以字典的形式解包
结果如下:
{'a': 11, 'b': 22, 'c': 33, 'd': 44, 'e': 55}
5、混合传递:
在定义函数或调用函数时混合使用需遵循的规则:
(1)定义函数的规则:
带有默认值的参数必须位于普通参数之后。
|
带有“*”标识的参数必须位于带有默认值的参数之后。 |
带有“**”标识的参数必须位于带有“*”标识的参数之后。
|
(2)调用函数的规则:
优先按位置参数传递的方式。
|
然后按关键字参数传递的方式。
|
之后按默认参数传递的方式。
|
最后按打包传递的方式。
|
def test(a, b, c=33, *args, **kwargs):
print(a, b, c, args, kwargs)
test(1, 2)
test(1, 2, 3)
test(1, 2, 3, 4)
test(1, 2, 3, 4, e=5)
结果如下:
1 2 33 () {}
1 2 3 () {}
1 2 3 (4,) {}
1 2 3 (4,) {'e': 5}
函数的返回值:
- return语句:在函数结束时将数据返回给程序,同时让程序回到函数被调用的位置继续执行。
- 在返回时有多个值,那么这些值将被保存到元组中。
def word(words):
if "山寨" in words:
new_word = word.replace("山寨", "**") # 将关键字替换为**
return new_word
result = word("这个手机是山寨版吧!") # 返回函数值
print(result)
# 在返回时有多个值
def move(x, y, step):
nx = x + step
ny = y - step
return nx, ny # 使用return语句返回多个值
result = move(100, 100, 60)
print(result)
结果如下:
这个手机是**版吧!
(160, 40)
变量作用域
- 根据作用域的不同将变量划分为局部变量和全局变量。
1、局部变量:函数内部定义的变量,只能在函数内部被使用。不同函数内部可以定义同名的局部变量,它们互不影响。
def a():
number = 10 # 定义局部变量
print(number) # 函数内部访问局部变量
a()
print(number) # 函数外部访问局部变量会报错
删掉函数外部访问局部变量的语句则得出以下结果:
2、全局变量:作用范围在整个程序中。全局变量在函数内部只能被访问,而无法直接修改。
number = 10 # 定义一个全局变量
def test_one():
print(number) # 在函数内部访问全局变量
test_one()
print(number) # 在函数外部访问全局变量
结果如下:
10
10
3、global和nonlocal关键字:用关键字修饰变量以间接修改函数内部的全局变量或在嵌套函数的外层函数声明的变量。
(1)global关键字
number = 10 # 定义全局变量
def test_one():
global number # 使用global声明变量number为全局变量
number += 1
print(number)
test_one()
print(number)
结果如下:
11
11
(2)nonlocal关键字
def test():
number = 10
def test_in():
nonlocal number #使用nonlocal修改嵌套作用域中定义的变量
number = 20
test_in()
print(number)
test()
结果如下:
20
特殊形式的函数:
1、递归函数:函数内部调用了自身。
# 计算一个数的阶乘
def func(num):
if num == 1: # 边界条件
return 1
else:
return num * func(num - 1) #递归公式
num = int(input("请输入一个整数:"))
result = func(num)
print("%s!=%d"%(num,result))
结果如下:
请输入一个整数:12
12!=479001600
2、匿名函数:使用lambda关键字定义匿名函数。
# 定义匿名函数,并将它返回的函数对象赋值给变量temp
temp = lambda x : pow(x, 2)
print(temp(10))
结果如下:
100