目录
[一. 函数的定义和调用](#一. 函数的定义和调用)
[二. 函数的返回值](#二. 函数的返回值)
[三. 变量的作用域](#三. 变量的作用域)
[四. 函数的链式调用](#四. 函数的链式调用)
[五. 函数的嵌套调用](#五. 函数的嵌套调用)
[六. 函数的递归调用](#六. 函数的递归调用)
[七. 函数参数的默认值](#七. 函数参数的默认值)
[八. 关键字传参](#八. 关键字传参)
一. 函数的定义和调用
函数,指一段可以被重复调用的代码。在python中,函数定义的语法如下:
def 函数名称(参数列表):
函数体
return 返回值 # 可以省略
如下代码,定义函数calcSum,获取从buttom ~ upper的累加,并调用函数计算1~100的累加。
函数定义和调用注意事项:
- 函数定义要在函数调用之前。
- 函数的形参个数和与实参保持一致。
函数调用的语法格式:
-
函数名称(实参列表)
-
返回值 = 函数名称(实参列表)
def calcSum(buttom, upper):
ret = 0
for i in range(buttom, upper + 1):
ret += i
return retprint(calcSum(1, 100))
对于实参的格式,python不像C/C++这般严格,但是,++要保证传给函数的实参能够进行函数中的全部运算++。如下面的代码,定义函数add(x,y),在函数内部计算x+y并输出结果,可以传递两个整形数据,也可以传两个字符串类型数据,但是传一个整形一个字符串就不可以。
def add(x, y):
print(f'{x} + {y} = {x + y}')
add(10, 20) # 10 + 20 = 30
add('Hello', 'World') # Hello + World = HelloWorld
# TypeError: unsupported operand type(s) for +: 'int' and 'str'
# add(10,'aaa')
二. 函数的返回值
与C/C++中的函数只能有一个返回值不同,python的函数允许有多个返回值,接收多个返回值的语法,类似于多元赋值。
**函数返回多个值的语法:**return VAL1, VAL2, ...
**接收多个函数返回值的语法:**val1,val2,... = 函数名(实参列表)
如果希望只接受多个返回值中的一个,则可以用下划线('_') 来占位表示省略。如 _, y = Func() 表示只接受Func函数的第二个返回值。
如下代码,定义了getPoint函数,返回两个值x,y,并对函数返回值进行接收。
def GetPoint():
x = input('请输入x的值:')
y = input('请输入y的值:')
return x, y
x1, y1 = GetPoint() # 获取GetPoint函数的两个返回值
_, y2 = GetPoint() # 只获取GetPoint函数的第二个返回值
print(f'x1 = {x1}, y1 = {y1}')
print(f'y2 = {y2}')
三. 变量的作用域
在python中,定义在函数内部的变量为局部变量,定义在函数外的变量为全局变量。
如下代码,在全局定义变量x=10,在test函数内部定义语句x=20,当在函数内部使用每个变量时,会现在局部查找是否有这个变量,如果有,那么就使用局部变量,如果没有,就向外层查找使用的变量。
x = 10 # 全局变量x
def test():
x = 20 # 属于test作用域的局部变量
print(f'x = {x}') # 输出局部变量值x = 20
test()
print(f'x = {x}') # 输出全局变量值x = 10
如果希望在函数内部对全局变量进行控制,那么需要使用global关键值声明变量为全局变量。
**global关键字:**声明变量为全局属性。
x = 10 # 全局变量x
def test():
global x # global关键字声明全局变量
x = 20 # 将全局变量x的值更改为20
test()
print(f'x = {x}') # x = 20
注意:在C/C++中,定义在for、while、if 等后面跟随的{ }表示的作用域中的变量,无法在{ }外面调用。但是,++在python中,定义在for、while、if作用域内的变量,可以在其外面被调用++。当然,无论是C/C++还是python,定义在函数内部的局部变量都不能在函数外面被调用。
for i in range(1, 11):
x = 100
print(f'i = {i}') # i = 10
print(f'x = {x}') # x = 100
四. 函数的链式调用
**链式调用:**一个函数的返回值,作为另一个函数的参数。
如下代码,在调用test函数时,使用add函数的返回值作为实参。
def add(x, y):
return x + y
def test(x, y):
print(f'x = {x}')
print(f'y = {y}')
# 链式调用,使用add函数的返回值充当test函数的实参
test(add(10, 20), add(30, 50))
五. 函数的嵌套调用
**嵌套调用:**一个函数内部调用另一个函数。
如下代码,函数c中调用函数b,函数b中调用函数a,就是典型的函数嵌套调用。
def a():
print('a')
def b():
a()
print('b')
def c():
b()
print('c')
# 函数c中调用函数b, 函数b中调用函数a
c()
使用pyCharm的调试功能,可以查看函数调用的栈中情况,如图5.1为++开启调试的方法:单击鼠标右键,选择Debug 'XXX'++,开始进行调试。
图5.1 以调试方法运行程序
开启调试后,程序首先运行至第一个断点位置,使用如下两个按键进行逐语句调试:
- **Step Over (F8):**遇到函数调用不进入函数。
- **Step Into (F7):**遇到函数调用就进入函数运行。
图5.2 pyCharm调试代码
六. 函数的递归调用
函数的递归调用,即:函数自己调用自己。编写递归函数时,有以下几点注意事项:
- 要有递归终止条件。
- 在递归调用中要越来越靠近终止条件。
- 递归层次不能太深,以防栈溢出。
如下代码,使用递归的方法编写函数,计算n!。
def factorial(n):
if n == 1:
return 1
return n * factorial(n - 1)
print(factorial(5))
**递归的优点:**代码编写简单。
递归的缺点:
- 执行过程复杂,程序运行效率低。
- 如果递归层次过深,容易出现栈溢出问题。
一般来说,使用递归编写的代码,都可以使用循环来替代。
七. 函数参数的默认值
在C++中,函数定义是支持缺省参数的,即:如果不显示给定实参的值,就采用默认的值。在python中,缺省参数同样也是被支持的,并且与C++一样,++带有缺省值的形参必须放在函数的参数列表最右侧++。
如下代码所示,定义add函数,并引入缺省参数debug,默认为False,调用时若不显示给定debug的值,那么就默认为False,显示给定就采用给定的值。
def add(x, y, debug = False):
if debug == True:
print(f'x = {x}, y = {y}')
return x + y
print(add(10, 20))
print(add(100, 200, True))
八. 关键字传参
对于C/C++,必须保证调用函数时的实参与对应形参在函数参数列表中的位置一一对应,这种传参的方法称为位置传参。
python在C/C++的基础之上,引入了关键字传参,++关键字传参,通过指定形参的名称来传递参数++,如下代码,定义函数test(x, y),并通过关键字传参进行调用。
def test(x, y):
print(f'x = {x}, y = {y}')
# 关键字传参调用函数
test(x=10, y=20)
test(y=20, x=10)
python支持位置传参与关键字传参共同使用,共同使用时必须保证位置参数在前,关键字参数在后。如下代码,定义函数test(x, y, z),通过语句test(10, z=30, y=20)调用函数,形参x在形参列表的第一个位置,可以进行位置传参,后面两个参数则通过关键字传参。
def test(x, y, z):
print(f'x = {x}, y = {y}, z = {z}')
# 关键字传参调用函数
test(10, z=30, y=20)