Python 函数详解:从创建、调用到参数的全方位指南
第 5 章 Python 函数详解
在 Python 项目开发中,函数是实现代码复用、提升开发效率的核心工具。本章将带你从基础的函数创建,到灵活多样的参数使用,一步步掌握 Python 函数的核心用法。
5.1 函数的创建
5.1.1 函数的介绍
Python 提供了丰富的内置函数(如print()、len()),但在实际开发中,这些内置函数往往无法满足项目的特定需求。因此,Python 允许我们自定义函数,通过封装一段代码来实现特定功能,实现一次定义、多次调用,大幅减少重复代码。
注意区分两个概念:
- 定义函数:创建一个新的函数(如
def fun1():)- 调用函数:使用已经定义好的函数(如
fun1())
5.1.2 函数的定义(def 语句)
创建新函数的过程称为定义函数,使用def关键字,格式如下:
python
def 函数名(参数):
代码块
return 返回值
使用def语句定义函数时,需要注意以下 5 点:
def是 Python 的保留字,用于声明函数,语句末尾必须有冒号:。- 函数名的命名规则与变量相同,由字母、数字、下划线组成,不能以数字开头。
()中的参数表示函数接收的数据,可根据功能需求决定是否设置参数。- 函数内的代码块必须缩进一个制表符(4 个空格),表示属于函数的执行逻辑。
return语句用于将函数的执行结果返回给调用处,若不需要返回数据,可省略。
示例:创建一个简单的无参函数
python
# 定义函数
def fun1():
# 函数代码块:输出0~9
for i in range(10):
print(i, end='')
这个函数没有参数,功能是输出数字 0~9。定义时,Python 不会执行函数内的代码,只有调用时才会执行。
5.1.3 函数的调用
定义好函数后,需要通过调用函数来执行它的功能。调用格式如下:
python
函数名(参数)
示例:调用无参函数
python
# 定义函数
def fun1():
for i in range(10):
print(i, end='')
# 调用函数
fun1()
plaintext
0123456789
⚠️ 重要注意:函数必须先定义,后调用!如果把调用写在定义前面,会出现NameError错误:
python
# 错误写法:先调用后定义
fun1() # 报错:name 'fun1' is not defined
def fun1():
for i in range(10):
print(i, end='')
这是因为代码是从上到下执行的,执行到调用语句时,系统还没有标记到函数的定义位置。
5.1.4 函数的复用
函数的最大优势就是复用性:一次定义,多次调用,避免重复编写相同的代码块。
示例 1:阶乘函数的复用
python
# 定义阶乘函数:计算n的阶乘
def fun3(n):
b = 1
for i in range(1, n + 1):
b = int(i) * b
return b
# 复用函数:计算7! + 8! + 9! 的和
b = fun3(7) + fun3(8) + fun3(9)
print(b)
plaintext
408240
可以看到,我们只编写了一次阶乘的逻辑,就可以通过调用函数,计算多个数的阶乘,代码非常简洁。
示例 2:学生成绩统计函数的复用
python
# 定义函数:接收姓名、数学和计算机成绩,输出平均分
def fun5(name, math, computer):
average = (math + computer) / 2
print(name, ':\t数学成绩:', math, '\t计算机成绩:', computer, '\t平均成绩:', average)
# 调用函数,传入不同学生的数据
fun5('张三', 90, 89)
fun5('李四', 98, 84)
fun5('王五', 91, 80)
plaintext
张三 : 数学成绩: 90 计算机成绩: 89 平均成绩: 89.5
李四 : 数学成绩: 98 计算机成绩: 84 平均成绩: 91.0
王五 : 数学成绩: 91 计算机成绩: 80 平均成绩: 85.5
只需要 1 行调用代码,就能输出一名学生的成绩信息,大幅提升了代码编写效率,同时降低了出错率。
5.1.5 return 返回值
return语句的核心功能是将函数执行后的结果返回给调用函数的地方,共有 4 种使用方式:
1. 带 return 语句,返回一个值
python
def fun2():
ls = ['张三', '李四']
a = len(ls)
# return将a的值返回给调用处
return a
print(fun2())
plaintext
2
2. 不带 return 语句
如果函数中没有return语句,函数执行完后会默认返回None。
python
def fun1():
for i in range(10):
print(i, end='')
# 打印函数的返回值
print(fun1())
plaintext
0123456789None
3. 带 return 语句,返回多个值
多个值会以元组的形式返回给调用处。
python
def fun2():
a = 2
b = '李四'
# 同时返回a和b两个值
return a, b
print(fun2())
plaintext
(2, '李四')
4. return 语句位于非末尾,提前结束函数
函数中可以存在多个return语句,执行到return时,函数会立即结束,后续代码不会执行。
python
def fun2(flag):
a = 2
b = '李四'
if flag:
# 条件满足时,直接返回b的值,函数结束
return b
# 条件不满足时,返回a和b
return a, b
print(fun2(True))
plaintext
李四
5.2 函数的参数
前面的示例中,我们用到了无参和带参函数。在实际开发中,函数的参数形式非常灵活,下面将详细讲解 Python 函数的参数用法。
5.2.1 形参和实参
- 形参(形式参数):定义函数时,
()中的参数变量,用于接收调用时传递的数据。 - 实参(实际参数):调用函数时,
()中传入的真实数据,会按顺序复制给对应的形参。
格式:
python
# 定义函数:形参
def 函数名(形参1, 形参2, ...):
代码块
return 返回值
# 调用函数:实参
函数名(实参1, 实参2, ...)
使用形参和实参时,需要注意以下 5 点:
- 形参是变量,用于接收实参传递的数据。
- 多个形参之间用逗号
,隔开。 - 实参的个数必须和形参的个数相同。
- 调用时,实参会按顺序依次复制给形参。
示例:输入数字求阶乘
python
# 定义函数:形参n接收要计算阶乘的数字
def fun3(n):
b = 1
for i in range(1, n + 1):
b = int(i) * b
return b
# 输入一个数字,作为实参传递给函数
a = input("请输入一个数字:")
print(a, '的阶乘:', fun3(int(a)))
运行结果(输入数字 5):
plaintext
请输入一个数字:5
5 的阶乘: 120
fun3(n)中的n是形参,用于接收实参数据。fun3(int(a))中的int(a)是实参,将用户输入的数字传递给形参n。
5.2.2 默认参数
当定义函数时,如果某些参数在大多数场景下都使用固定值,可以设置为默认参数,提前给形参设置一个默认数据。
格式:
python
def 函数名(必填参数, 默认参数=默认值):
代码块
return 返回值
使用默认参数的注意事项:
- 形参中,
形参2=数据2表示将数据 2 赋值给形参 2,也叫默认参数。 - 调用函数时,如果不传入实参 2,形参 2 会自动使用默认值;如果传入了实参 2,则会覆盖默认值。
- 必填参数必须写在默认参数前面,否则会引发语法错误。
示例:计算圆的面积
python
# 定义函数:r为必填参数,pi为默认参数,默认值3.14
def circle_s(r, pi=3.14):
return r * r * pi
# 调用函数:不传入pi,使用默认值
a = circle_s(3)
# 调用函数:不传入pi,使用默认值
b = circle_s(5)
print(a + b)
plaintext
106.76
如果需要提高计算精度,可以传入实参覆盖默认值:
python
# 传入实参3.1415926,覆盖pi的默认值
print(circle_s(6, 3.1415926))
也可以通过指定参数名的方式传递数据,此时参数的顺序可以与定义时不同:
python
# 指定参数名传递,顺序不受限制
a = circle_s(pi=3.14159, r=3)
print(a)
错误示例:必填参数写在默认参数后面
python
# 错误写法:必填参数r在默认参数pi后面,语法错误
def circle_s(pi=3.14, r):
return r * r * pi
5.2.3 可变参数
当不确定函数需要接收的参数个数时,可以使用可变参数,在形参前加一个*,即可将其转换为可变参数,以元组的形式接收所有剩余数据。
格式:
python
def 函数名(必填参数, *可变参数):
代码块
使用可变参数的注意事项:
- 可变参数的形参必须以
*开头。 - 可变参数必须位于必填参数的右边,保证必填参数先接收数据。
- 可变参数以元组的形式接收数据。
示例:可变参数的使用
python
def fun3(a, *b):
print(b)
c = 0
# 遍历可变参数b中的每个值,与a相乘后累加
for i in b:
c += a * i
return c
print(fun3(3, 1, 2, 3))
plaintext
(1, 2, 3)
18
- 实参 3 复制给必填参数
a。 - 剩余的 1、2、3 全部传递给可变参数
b,以元组形式存储。
5.2.4 关键字参数
关键字参数以**开头,与可变参数类似,但它以字典的形式接收数据,适用于接收带键值对的参数。
格式:
python
def 函数名(必填参数, **关键字参数):
代码块
使用关键字参数的注意事项:
- 关键字参数的形参必须以
**开头。 - 关键字参数必须位于必填参数的右边。
- 关键字参数以字典的形式接收数据,传递的数据需要包含键和值,用等号连接。
示例:关键字参数的使用
python
def fun4(a, **b):
print(a, '课程考试成绩:')
print(b)
# 调用函数,关键字参数以键值对形式传递
fun4('Python', zhangsan=90, lisi=95)
plaintext
Python 课程考试成绩:
{'zhangsan': 90, 'lisi': 95}
5.3 函数的变量作用范围
根据变量的作用范围,Python 变量分为全局变量和局部变量,两者的区别和使用场景是本节的核心。
5.3.1 局部变量与全局变量
- 局部变量:在函数内部定义的变量,只能在函数内部使用,函数外部无法访问。
- 全局变量:在函数外部定义的变量,在整个代码文件中都可以使用,函数内部也能直接访问。
示例 1:局部变量的作用域
python
def fun5(a, b, c=10):
d = a*a + b*b + c*c
return d
fun5(1, 2, 3)
print(a) # 报错
plaintext
NameError: name 'a' is not defined
a、b、c是函数fun5的形参,属于局部变量;d是函数内部定义的变量,也属于局部变量。在函数外部无法访问这些变量,因此print(a)会报错。
示例 2:函数内访问全局变量
python
def fun5(a, b, c=10):
d = a*a + b*b + c*c + e
return d
e = 100 # 全局变量
print(fun5(1, 2, 3))
plaintext
114
函数内部可以直接访问全局变量e,因此代码可以正常运行。
5.3.2 函数中修改全局变量的问题
当函数内对全局变量直接赋值时,Python 会默认创建一个同名的局部变量,导致逻辑错误。
错误示例:修改全局变量时的常见错误
python
def fun7(b):
print('a+b的值:', a+b)
a = 2 # 试图修改全局变量a,Python会创建局部变量a
print('a+b的值:', a+b)
a = 3 # 全局变量
fun7(13)
print('a的值:', a)
plaintext
Traceback (most recent call last):
...
UnboundLocalError: local variable 'a' referenced before assignment
报错原因:Python 在函数内看到对a的赋值语句,会默认创建局部变量a,但在赋值前先执行了print('a+b的值:', a+b),此时局部变量a还未定义,因此报错。
同名变量互不影响
python
def fun7(b):
a = 2 # 局部变量a,和全局变量a无关
print('a+b的值:', a+b)
a = 3 # 全局变量
fun7(13)
print('a的值:', a)
plaintext
a+b的值: 15
a的值: 3
函数内的a是局部变量,和全局变量a只是名字相同,实际是两个不同的变量,因此修改局部变量不会影响全局变量。
5.3.3 global 声明全局变量
如果需要在函数内修改全局变量,必须使用global关键字声明,告诉 Python 这是全局变量,而非局部变量。
示例:使用 global 声明全局变量
python
def fun7(b):
global a # 声明a是全局变量
print('a的值:', a)
a = 2 # 修改全局变量a
print('a+b的值:', a+b)
a = 3 # 全局变量
fun7(13)
print('a的值:', a)
plaintext
a的值: 3
a+b的值: 15
a的值: 2
使用global声明后,函数内的a就是全局变量,修改后会影响函数外部的全局变量值。
5.4 导入其他模块中的函数
在项目开发中,我们会将不同功能的代码写在不同文件中,通过模块导入的方式在当前文件中使用其他文件的函数,实现模块化开发。
5.4.1 导入整个模块
使用import关键字导入整个文件模块,格式如下:
python
import 文件名
调用时需要加上文件名,格式:文件名.函数名(参数)
示例:导入 a.py 文件中的 fun6 函数
a.py 文件代码:
python
def fun6(n):
b = 1
for i in range(1, n+1):
b = int(i) * b
return b
b.py 文件代码:
python
import a # 导入a.py模块
print(a.fun6(6)) # 调用a模块中的fun6函数
运行 b.py 的结果:
plaintext
720
导入多个模块时,可以用逗号分隔:
python
import a, b, c
5.4.2 导入文件中的指定函数
如果只需要使用文件中的某个函数,可以使用from...import语句导入指定函数,格式:
python
from 文件名 import 函数名
调用时无需添加文件名,直接使用函数名即可。
示例:导入 a1.py 中的 fun6 函数
a1.py 文件代码:
python
def fun6(n):
b = 1
for i in range(1, n+1):
b = int(i) * b
return b
def fun7():
print("这是fun7函数")
def fun8():
print("这是fun8函数")
b1.py 文件代码:
python
from a1 import fun6 # 仅导入fun6函数
print(fun6(6)) # 直接调用fun6
plaintext
720
导入多个指定函数时,用逗号分隔:
python
from a1 import fun6, fun8
5.4.3 导入文件中的全部函数
如果需要使用文件中的所有函数,可以使用from...import *语句,格式:
python
from 文件名 import *
调用时无需添加文件名,直接使用所有函数名。
示例:导入 a1.py 中的所有函数
python
from a1 import *
print(fun6(6))
fun7()
fun8()
plaintext
720
这是fun7函数
这是fun8函数
5.4.4 给导入的函数设置别名
当模块或函数名较长时,可以使用as关键字设置别名,简化调用。
- 给模块设置别名:
import 文件名 as 新模块名 - 给函数设置别名:
from 文件名 import 函数名 as 新函数名
示例:设置别名
python
# 给模块设置别名
import a as t
print(t.fun6(6))
# 给函数设置别名
from a import fun6 as f6
print(f6(6))
5.4.5 __name__属性与模块测试
__name__属性用于获取当前文件的名称:
- 当文件是主文件(直接运行的文件)时,
__name__的值为__main__。 - 当文件是次文件(被导入的文件)时,
__name__的值为文件名。
我们通常利用if __name__ == '__main__':语句,让测试代码仅在直接运行文件时执行,被导入时不执行。
示例:模块测试代码
a6.py 文件代码:
python
def fun6(n):
print(__name__) # 输出当前文件的__name__属性
b = 1
for i in range(1, n+1):
b = int(i) * b
return b
if __name__ == '__main__':
print(fun6(5)) # 仅当直接运行a6.py时执行
- 直接运行 a6.py,输出:
plaintext
__main__ 120 - 从 b6.py 导入 a6.py:
python
import a6 print(a6.fun6(5))plaintext
此时a6 120if __name__ == '__main__':中的代码不会执行,仅执行了fun6函数内的代码。
5.5 排序函数 sorted () 详解
sorted()函数可以对所有可迭代的数据对象(如列表、字符串、元组)进行排序,比列表的sort()方法更灵活。
5.5.1 sorted () 函数的基本用法
sorted()函数的通用格式:
python
sorted(iterable, key=None, reverse=False)
iterable:可迭代对象,如列表、字符串、元组。key:表示比较的函数,常和 lambda 配合使用。reverse:排序顺序,False为升序(默认),True为降序。
示例 1:对列表进行升序 / 降序排序
python
a = [3, 7, 9, 4, 0, 2]
b = sorted(a) # 默认升序
c = sorted(a, reverse=True) # 降序
print(b)
print(c)
plaintext
[0, 2, 3, 4, 7, 9]
[9, 7, 4, 3, 2, 0]
示例 2:对字符串按 Unicode 顺序排序
python
d = sorted('nfweubvy')
print(d)
plaintext
['b', 'e', 'f', 'n', 'u', 'v', 'w', 'y']
字符串按每个字符的 Unicode 值从小到大排序。
5.5.2 结合 lambda 实现自定义排序
通过key参数传入 lambda 函数,可以实现自定义规则排序。
示例:按元素减去 5 后的绝对值排序
python
a = [3, 7, 9, 4, 0, 2]
b = sorted(a, key=lambda x: abs(x-5))
print(b)
plaintext
[4, 3, 7, 2, 9, 0]
排序规则:先计算每个元素x减去 5 的绝对值,再按绝对值从小到大排序,最终结果为[4, 3, 7, 2, 9, 0]。
5.6 匿名函数 lambda
lambda 是 Python 的保留字,用于创建简单的匿名函数,格式如下:
python
函数名 = lambda 参数: 函数表达式
lambda 函数只能包含一个表达式,执行后会自动返回结果,无需使用return语句。
示例 1:定义一个加法 lambda 函数
python
# 定义lambda函数,实现x+y
fun1 = lambda x, y: x + y
# 调用函数
print(fun1(3, 4))
plaintext
7
等价于以下普通函数:
python
def fun1(x, y):
return x + y
示例 2:将lambda作为函数的参数
函数语法
python
sorted(iterable, key=None, reverse=False)
| 参数 | 说明 |
|---|---|
iterable |
可迭代对象,如列表、字符串、元组 |
key |
比较函数,用于自定义排序规则,常与 lambda 配合使用 |
reverse |
排序顺序:False 为升序(默认),True 为降序 |
基础排序示例
1. 列表升序 / 降序排序
python
# 原始列表
a = [3, 7, 9, 4, 0, 2]
# 1. 默认升序排序
c = sorted(a)
print("升序排序结果:", c)
# 2. 设置 reverse=True 实现降序排序
d = sorted(a, reverse=True)
print("降序排序结果:", d)
plaintext
升序排序结果: [0, 2, 3, 4, 7, 9]
降序排序结果: [9, 7, 4, 3, 2, 0]
2. 字符串排序(按 Unicode 码值)
sorted() 对字符串排序时,会按照每个字符的 Unicode 码值从小到大排列。
python
# 原始字符串
b = 'nfweubvy'
# 对字符串排序
e = sorted(b)
print("字符串排序结果:", e)
plaintext
字符串排序结果: ['b', 'e', 'f', 'n', 'u', 'v', 'w', 'y']
例如字母 'b' 的 Unicode 值小于 'c',因此排在前面。
结合 lambda 实现自定义排序
通过 key 参数传入 lambda 匿名函数,可以实现自定义规则排序,这是 sorted() 函数最强大的用法之一。
示例:按「元素与 5 的距离」排序
需求:将列表 [3, 7, 9, 4, 0, 2] 按「每个元素减去 5 后的绝对值」从小到大排序。
python
# 原始列表
a = [3, 7, 9, 4, 0, 2]
# 使用 lambda 定义排序规则:按 abs(x-5) 的值排序
b = sorted(a, key=lambda x: abs(x-5))
print("按与5的距离排序结果:", b)
plaintext
按与5的距离排序结果: [4, 3, 7, 2, 9, 0]更多推荐


所有评论(0)