05函数入门

05函数入门

_

注:学习资料来源<尚硅谷>

视频:点击跳转

代码仓库:pythonStudy

函数是 Python 编程中最核心的概念之一。作为一名开发者,你一定听过“不要重复造轮子”这句话——函数就是让我们把一组逻辑封装起来,在需要时重复使用,既能减少代码量,又能提升可读性。今天这篇博客将带你从零开始,系统掌握 Python 函数的所有关键知识点。


1. 函数的概念与分类

1.1 什么是函数?

函数 是组织好的、可重复使用的、用来实现单一或相关联功能的代码块。

打个比方:函数就像你家里的智能场景面板,你提前把“回家模式”设置好——打开灯光、拉上窗帘、播放音乐。之后你只需要说一句“回家模式”,所有设置好的动作就会自动执行。函数的道理一模一样,提前写好一段代码,需要时直接调用即可。

使用函数能带来几个明显的好处:

  • 减少重复:相同逻辑只写一次,到处调用。

  • 结构清晰:把复杂程序拆分成若干个小模块。

  • 便于维护:修改一处,所有调用的地方都会生效。

  • 易于复用:一个函数写好,可以在不同项目里多次使用。

1.2 Python 函数的三大类

Python 中的函数可以分为三类:

  1. 内置函数
    Python 自带的函数,比如 print()len()sum()type() 等,不需要额外导入就能直接用。
    📚 官方内置函数文档

  2. 模块提供的函数
    需要先导入对应的模块才能使用。例如 math.sqrt()random.randint()os.path.join()
    📚 官方模块索引

  3. 自定义函数
    由开发者自己使用 def 关键字定义的函数。这也是我们今天的重头戏。


2. 函数的基本使用

2.1 定义函数

最简单的函数定义长这样:

def 函数名():
    函数体
  • def 是定义函数的关键字。

  • 函数名要符合标识符命名规范(字母、数字、下划线,不能以数字开头)。

  • 定义完函数不会立即执行,必须调用才会运行。

下面是一个欢迎函数:

def welcome():
    print("欢迎来到 Python 课堂!")
    print("Python 让编程更简单!")

2.2 调用函数

调用函数只需在函数名后加上小括号:

welcome()   # 函数体内的代码会立即执行
welcome()   # 可以多次调用

⚠️ 注意:函数必须先定义,后调用。如果顺序反了,Python 会报错。


3. 函数的参数

没有参数的函数只能做固定的事;有了参数,函数就变得灵活而强大。

3.1 参数的作用

假设我们想写一个点餐程序,没有参数时:

def order():
    num = 1
    dish = "辣椒炒肉"
    print(f"您点的是:{num}份 {dish}")

order()

这个函数每次点餐都只能是一份辣椒炒肉,明显不够用。加了参数之后:

def order(num, dish):
    print(f"您点的是:{num}份 {dish}")

order(1, "辣椒炒肉")
order(2, "辣子鸡")

3.2 形参 vs 实参

  • 形参(形式参数):定义函数时括号里的变量,用来接收调用时传进来的值。

  • 实参(实际参数):调用函数时实际传入的具体数据。

形参只在函数体内有效,函数执行完毕,形参也随之销毁。

3.3 位置参数

调用时,按照形参定义的顺序依次传入实参,这就是位置参数。

def order(num, dish):
    print(f"您点的是:{num}份 {dish}")

order(3, "宫保鸡丁")   # 3 -> num, "宫保鸡丁" -> dish

⚠️ 实参的个数、顺序必须和形参一致,否则会出错或造成数据错乱。

3.4 关键字参数

不想记顺序?可以用 形参名=值 的方式传递,这就是关键字参数。

def greet(name, gender, age, height):
    print(f"我叫{name},性别{gender},年龄{age},身高{height}cm")

greet(name="张三", gender="男", age=18, height=172)
greet(height=172, age=18, gender="男", name="张三")   # 顺序完全自由

位置参数和关键字参数可以混用,但位置参数必须放在关键字参数之前

greet("张三", "男", height=172, age=18)   # ✅ 正确
# greet(height=172, age=18, "张三", "男") # ❌ 错误

3.5 限制传参方式(/*

如果你想强制调用者使用特定的传参方式,可以用 /*

  • / 前面的参数只能使用位置参数。

  • * 后面的参数只能使用关键字参数。

def greet(name, /, gender, *, age, height):
    print(f"我叫{name},性别{gender},年龄{age},身高{height}cm")

greet("张三", "男", age=18, height=172)          # ✅
greet("张三", gender="男", age=18, height=172)  # ✅
# greet(name="张三", gender="男", age=18, height=172) # ❌ name在/前面,不能用关键字

3.6 参数默认值

有些参数大部分情况下都取同一个值,这时可以给它一个默认值。调用时如果不传,就使用默认值;传了则覆盖。

def greet(name, gender, age, height, msg="你好"):
    print(f"我叫{name},性别{gender},年龄{age},身高{height}cm")
    print(f"我想说:{msg}")

greet("张三", "男", 18, 172)            # msg = "你好"
greet("张三", "男", 18, 172, "hello")  # msg = "hello"

⚠️ 有默认值的形参必须放在所有必选参数(无默认值)的后面,否则语法错误。

3.7 可变参数:*args**kwargs

如果不知道调用者会传多少个参数,怎么办?用可变参数!

  • *args:把多个位置参数打包成一个元组

  • **kwargs:把多个关键字参数打包成一个字典

def test1(*args):
    print("位置参数元组:", args)

test1("张三", "男", 18, 172)
# 输出:位置参数元组: ('张三', '男', 18, 172)

def test2(**kwargs):
    print("关键字参数字典:", kwargs)

test2(name="张三", gender="男", age=18, height=172)
# 输出:关键字参数字典: {'name': '张三', 'gender': '男', 'age': 18, 'height': 172}

两者同时使用时,*args 必须放在 **kwargs 之前。

def func(a, b, *args, c="Python", **kwargs):
    print("a:", a, "b:", b, "c:", c)
    print("args:", args)
    print("kwargs:", kwargs)

func("张三", "男", "抽烟", "喝酒", age=18, height=172)

3.8 特殊的字面量 None

None 表示空值、无意义。它的类型是 NoneType

  • 在布尔判断中,None 被视为 False

  • 不能与数字相加,也不能与字符串拼接。

  • 函数如果没有写 return,或只写了 return 但不带值,默认返回的就是 None

常见用法:

msg = None            # 暂时不清楚 msg 将来存什么
if not msg:
    print("msg 是空的")

4. 返回值

函数不仅能干活,还能把结果“交回来”,这就是返回值

使用 return 关键字:

  • 立即结束函数运行。

  • return 后面的值作为函数的返回值抛给调用者。

def add(n1, n2):
    return n1 + n2

result = add(100, 200)
print(result)   # 300

没有 return 的函数,或者只写 return 的函数,返回值默认为 None

result = print("hello")   # print 没有返回值
print(result)             # None

5. 全局作用域与局部作用域

作用域决定了变量的可访问范围。

5.1 全局变量

在函数外部定义的变量称为全局变量,整个程序都可以访问它。

5.2 局部变量

函数内部定义的变量称为局部变量,只能在函数体内使用。函数调用结束,局部变量就被销毁了。

5.3 global 关键字

如果想在函数内部修改全局变量的值,而不是创建一个同名局部变量,需要用 global 声明。

a = 100

def test():
    global a        # 声明 a 是全局变量
    a = 300
    print("函数内 a:", a)

test()
print("全局 a:", a)   # 300

如果没有 global,函数内部的 a = 300 只会创建一个新的局部变量,不会影响外部的 a

生命周期对比

  • 局部变量:函数调用时创建,函数结束时销毁。

  • 全局变量:程序启动时创建,程序结束时销毁。

# 局部变量的生命周期
def local_demo():
    m = 100
    m += 1
    print(f"局部 m: {m}")

local_demo()
local_demo()   # 每次 m 都重新初始化为 100

# 全局变量生命周期
n = 100
def global_demo():
    global n
    n += 1
    print(f"全局 n: {n}")

global_demo()
global_demo()
global_demo()   # n 会持续累加

6. 函数的嵌套调用

一个函数在执行过程中可以调用另一个函数,这被称为嵌套调用

def speak(msg):
    print("---" * 10)
    print(msg)
    print("---" * 10)

def greet(name, msg):
    print(f"我叫{name},我想说的话在下面:")
    speak(msg)
    print("我想说的结束了")

greet("张三", "你好啊")

多层嵌套也很常见,逻辑像俄罗斯套娃一样一层层深入,再一层层返回。

def test1():
    print("进入 test1")
    test2()
    print("退出 test1")

def test2():
    print("进入 test2")
    test3()
    print("退出 test2")

def test3():
    print("进入 test3")
    print("*** 执行 test3 ***")
    print("退出 test3")

test1()

7. 递归调用

递归是函数自己调用自己的一种编程技巧,非常适合解决可以拆分成子问题的问题。

但是递归必须要有终止条件,否则就会无限循环下去,直至栈溢出。

# 从大到小打印
def welcome(n):
    print(f"你好啊 {n}")
    if n > 1:
        welcome(n - 1)

welcome(5)

上面的代码会依次输出 “你好啊 5” 到 “你好啊 1”。

如果换成从小到大打印呢?只需要把 print 放到递归调用之后:

def welcome_asc(n):
    if n > 1:
        welcome_asc(n - 1)
    print(f"你好啊 {n}")

welcome_asc(5)

经典递归:求阶乘

def factorial(num):
    if num == 0:
        return 1
    else:
        return num * factorial(num - 1)

print(factorial(5))   # 120
print(factorial(6))   # 720

8. 函数说明文档

给函数加文档是一种好习惯。你只需要在函数体开头用三引号字符串写下说明即可。

def add(n1, n2):
    """
    计算两个数相加的结果。
    :param n1: 第一个数
    :param n2: 第二个数
    :return: 二者相加的结果
    """
    return n1 + n2

在 IDE 或 Jupyter 中,鼠标悬停或使用 help(add) 就能看到你写的文档,极大的方便了自己和团队其他成员。


9. 综合案例:健身挑战赛

最后,我们把前面学到的知识串起来,写一个有趣的小应用——记录三天健身数据,判断是否挑战成功。

def calc_total(*nums):
    """计算总运动量"""
    return sum(nums)

def calc_avg(total, days=7):
    """计算平均值"""
    return total / days

def check_success(total, goal=120):
    """判断挑战是否成功"""
    if total >= goal:
        return "✅ 恭喜!挑战成功!"
    else:
        return "❌ 抱歉!挑战失败!"

def main(title, duration, goal):
    print(f"【{title}】【{duration}天】挑战赛(请输入每天的数量)")
    num1 = int(input("第1天:"))
    num2 = int(input("第2天:"))
    num3 = int(input("第3天:"))
    
    total = calc_total(num1, num2, num3)
    avg = calc_avg(total, duration)
    result = check_success(total, goal)
    
    print(f"\n【{title}】【{duration}天】健身总结")
    print(f"总数:{total},平均值:{avg:.1f}")
    print(result)

# 启动挑战
main("俯卧撑", 3, 40)

运行这个程序,你就可以模拟一个三天俯卧撑挑战,程序会自动计算总数、平均值,并告诉你是否达成了目标。这里面用到了自定义函数、参数、可变参数、默认参数、返回值、用户输入、格式化输出等一系列知识,是函数综合运用的绝佳练习。


小结

恭喜你!现在你已经掌握了 Python 函数的全貌:

  • 如何定义与调用函数

  • 参数的各种玩法(位置、关键字、默认值、可变参数)

  • 返回值与 None

  • 变量的作用域与 global

  • 嵌套调用与递归

  • 编写文档和综合实战

下一步,可以尝试把今天学到的东西用在你的实际项目中,把重复的代码重构成函数。当你的函数越写越顺手时,你就真正走上了 Python 进阶之路。

练习建议:按照本文的知识点顺序,分别创建对应的 Python 文件,逐一练习,代码量不用多,重在体会每种用法的使用场景。


Happy Coding!


06数据容器 2026-04-24
04流程控制语句 2026-04-24

评论区