Python 函数的概念

函数是组织好的、可重复使用的代码块,用于实现单一或相关联的功能。本课将系统学习 Python 函数的定义与使用。

9
知识点
8+
代码示例
def 关键字
📋 本课学习内容

① 理解函数的概念(数学函数 vs Python 函数)

② 掌握函数的定义语法(def 关键字)

③ 理解形参与实参的区别

④ 掌握各类参数传递方式:位置参数、关键字参数、默认值、可变参数

⑤ 理解 *args**kwargs 的用法

💡
点击左侧导航栏的任意章节,开始学习!建议按顺序学习,每节都有可运行的代码示例。

什么是函数

从数学函数到 Python 函数

📐 数学上的函数

数学上的函数通常形如 y = f(x)z = g(x, y)

y = f(x) 中:f函数名x自变量y因变量

z = g(x, y) 中:g 是函数名,xy 是自变量,z 是因变量。

🐍 Python 中的函数

Python 中的函数与数学函数结构一致,每个函数都有自己的:

  • 函数名 给函数取一个名字(命名规则与变量相同)
  • 参数 函数的自变量,写在圆括号中
  • 返回值 函数的因变量,用 return 关键字返回
📝
命名规则提醒:函数名的命名规则与变量名完全相同——只能包含字母、数字和下划线,且不能以数字开头。
第一个函数示例
# 定义一个实现两数减法的函数
def sub(x, y):   # def 定义函数,函数名是 sub,参数是 x 和 y
    return x - y  # 函数返回值是 x - y

print(sub(1, 2))  # 输出:-1
print(sub(4, 6))  # 输出:-2
▸ 运行结果:
-1
-2

函数定义语法

使用 def 关键字定义函数

📖 基本语法
def 函数名(参数1, 参数2, ...):
    """函数文档字符串(可选)"""
    函数体代码
    return 返回值
组成部分说明示例
def定义函数的关键字def sub(x,y):
函数名函数的名称,遵循变量命名规则sub
参数函数的输入(自变量),放在 ()x, y
函数体缩进的代码块,实现具体功能return x - y
return返回函数值(因变量),可省略return x - y
⚠️
注意:函数定义时,函数名后面的圆括号必须有,即使函数没有参数也不能省略!
🔍 没有 return 的函数

如果函数中没有 return 语句,函数会返回代表空值的 None

def list1():
    for i in range(10):
        print(f" {i} ", end="")
    print()
    # 没有 return,但不代表没有返回值

list1()          # 输出: 0  1  2  3  4  5  6  7  8  9
print(list1())   # 输出:None
▸ 运行结果:
0 1 2 3 4 5 6 7 8 9
None

形参 vs 实参

形式参数与实际参数的区别

形式参数(形参)实际参数(实参)
定义函数定义时设置的参数函数调用时实际传入的参数
作用接收调用时传入的值提供给函数处理的实际数据
示例def sub(x, y):
这里的 x, y 是形参
sub(1, 2)
这里的 1, 2 是实参
📝 示例代码
def sub(x, y):   # x 和 y 是【形参】
    return x - y

result = sub(10, 3)  # 10 和 3 是【实参】
print(result)         # 输出:7
记忆口诀:定义时的是"形"(形式),调用时的是"实"(实际)。形参是"占位符",实参是"真数据"。
📌 无参数函数

函数也可以没有参数,但函数名后面的圆括号仍必须有:

def greet():
    print("Hello, Python!")

greet()  # 调用时无参数,但仍需写圆括号
▸ 运行结果:
Hello, Python!

位置参数

按位置顺序传递参数

📍 什么是位置参数

位置参数是最常见的参数类型。调用函数时,按照从左到右的顺序依次传入参数,传入参数的数量必须与定义时一致。

def sub(x, y):
    return x - y

print(sub(1, 2))  # x=1, y=2 → 输出:-1
print(sub(4, 6))  # x=4, y=6 → 输出:-2
⚠️
参数数量不匹配会报错!
# print(sub(3))
# TypeError: sub() missing 1 required positional argument: 'y'
# 少传了一个参数,Python 会报错

# print(sub(2, 3, 4))
# TypeError: sub() takes 2 positional arguments but 3 were given
# 多传了一个参数,Python 也会报错
调用方式结果说明
sub(1, 2)-1✅ 正确:两个参数,顺序对应
sub(1)❌ 报错参数少了
sub(1, 2, 3)❌ 报错参数多了

关键字参数

通过"参数名=参数值"传递参数

🔑 什么是关键字参数

如果不想按照从左到右的顺序传参,可以使用关键字参数,通过 参数名=参数值 的形式传入,这样就不依赖参数的位置了。

def sub(x, y):
    return x - y

# 位置参数:按顺序
print(sub(1, 2))       # x=1, y=2 → 输出:-1

# 关键字参数:按参数名
print(sub(y=1, x=2))   # x=2, y=1 → 输出:1
▸ 运行结果:
-1
1
⚠️
注意:关键字参数的参数名必须与函数定义时的参数名完全一致,否则会报错!
# print(sub(a=1, b=2))
# TypeError: sub() got an unexpected keyword argument 'a'
# 参数名 a、b 不存在于函数定义中,会报错
💡
混合使用:位置参数和关键字参数可以混合使用,但位置参数必须在关键字参数之前

强制位置参数 & 命名关键字参数

更精细的参数传递控制(Python 3.8+)

🔒 强制位置参数(/

在参数列表中使用 / 可以设置强制位置参数——/ 之前的参数只能按位置传递,不能使用关键字方式传参。

def sub1(x, y, /):   # / 之前的 x, y 必须是位置参数
    return x - y

print(sub1(2, 1))    # ✅ 正确:按位置传参
# print(sub1(x=2, y=1))  # ❌ 报错:x 和 y 不支持关键字传参
🏷️ 命名关键字参数(*

在参数列表中使用 * 可以设置命名关键字参数——* 之后的参数只能通过 参数名=参数值 的方式传递。

def sub2(*, x, y):   # * 之后的 x, y 必须是关键字参数
    return x - y

print(sub2(x=2, y=1))  # ✅ 正确:按关键字传参
# print(sub2(2, 1))     # ❌ 报错:x 和 y 必须用关键字传参
语法符号名称传参方式Python 版本
/强制位置参数只能按位置传参Python 3.8+
*命名关键字参数只能按关键字传参所有版本
💡
实际应用场景:当你设计一个函数,希望用户必须按照某种方式传参时(比如为了代码可读性),可以使用这两种语法来强制约束。

参数默认值

定义函数时为参数预设值

🎯 设置默认值

Python 允许在定义函数时,在参数列表中直接给参数赋值。调用函数时如果不传入该参数,就使用默认值。

def sub3(x=20, y=10):  # 定义时为参数设置默认值
    return x - y

print(sub3())        # 使用默认值:x=20, y=10 → 输出:10
print(sub3(3, 3))   # 传入新值:x=3,  y=3  → 输出:0
print(sub3(100))     # 只传 x:x=100, y=10 → 输出:90
print(sub3(y=5))     # 只传 y:x=20,  y=5  → 输出:15
▸ 运行结果:
10
0
90
15
⚠️
重要规则:带默认值的参数必须放在不带默认值的参数之后,否则会产生 SyntaxError 错误。
# ❌ 错误写法:带默认值的参数在不带默认值的参数前面
# def wrong(x=1, y):
#     pass
# SyntaxError: non-default argument follows default argument

# ✅ 正确写法:不带默认值的参数在前
def correct(y, x=1):
    pass
调用方式实际参数返回值
sub3()x=20, y=10(默认)10
sub3(3, 3)x=3, y=30
sub3(100)x=100, y=1090
sub3(y=5)x=20, y=515

可变参数 *args

传入任意数量的参数

什么是可变参数

有时候我们并不知道调用者会传入多少个参数,这时可以使用 *(星号)语法定义可变参数,允许函数接收 0 个或任意多个位置参数

传入的多个参数会被打包成一个元组(tuple)

def add(*x):       # *x 表示 x 是可变参数
    return sum(x)  # x 是一个元组,可以用 sum() 求和

print(add(1, 2))            # 输出:3
print(add(1, 2, 3, 4, 5))  # 输出:15
print(add())                 # 输出:0(没有参数时,x 是空元组)
▸ 运行结果:
3
15
0
💡
典型应用场景:团队开发中,你设计了一个函数给其他人使用,但无法预知其他人会传入多少个参数,这时可变参数非常有用。
📦 参数打包原理

当函数被调用时,所有"多余"的位置参数会被收集到一个元组中,赋值给 * 后面的变量:

def demo(*args):
    print(type(args))   # <class 'tuple'>
    print(args)         # 打印打包后的元组

demo(1, 2, 3)  # args = (1, 2, 3)
▸ 运行结果:
<class 'tuple'>
(1, 2, 3)

可变关键字参数 **kwargs

传入任意数量的关键字参数

什么是 **kwargs

如果希望通过 参数名=参数值 的形式传入若干个参数,且具体数量不确定,可以使用 **(双星号)定义可变关键字参数

传入的关键字参数会被打包成一个字典(dict)

def foo(*args, **kwargs):
    # *args   接收0个或任意多个位置参数 → 打包成元组
    # **kwargs 接收0个或任意多个关键字参数 → 打包成字典
    print("args: ", args)
    print("kwargs:", kwargs)

foo(3, 2.1, True, name='骆昊', age=43, gpa=4.95)
▸ 运行结果:
args: (3, 2.1, True)
kwargs: {'name': '骆昊', 'age': 43, 'gpa': 4.95}
语法名称打包类型传参方式
*args可变位置参数元组 tuple位置传参
**kwargs可变关键字参数字典 dict关键字传参
记忆技巧:*args* 像把多个值"串"起来(串成元组);**kwargs** 像字典的键值对(两个星号对应两个维度:键和值)。
🏁 知识总结

至此,你已经学习了 Python 函数的全部核心参数类型:

  • 位置参数 按位置顺序传参,数量必须匹配
  • 关键字参数名=值 传参,不受位置限制
  • / 强制位置 / 前的参数只能用位置传参
  • * 命名关键字 * 后的参数只能用关键字传参
  • 默认值 定义时赋值,调用时可省略
  • *args 接收任意个位置参数,打包成元组
  • **kwargs 接收任意个关键字参数,打包成字典