文章目录

目录

 

前言

第一章:变量作用域 —— 哪里的地盘哪里说了算

1.1 什么叫“作用域”?

1.2 局部变量 —— 只在函数内部有效

1.3 全局变量 —— 在整个文件都有效

1.4 在函数里想改全局变量?用 global

1.5 函数嵌套 + nonlocal —— 跨层修改

1.6 作用域规则总结

第二章:递归函数 —— 自己喊自己

2.1 什么是递归?

2.2 递归的两个关键要素

2.3 经典递归:阶乘

2.4 经典递归:斐波那契数列

2.5 递归注意事项

第三章:高阶函数 —— 函数也可以“被传来传去”

3.1 什么是高阶函数?

3.2 sorted() —— 自定义排序规则

3.3 filter() —— 筛选数据

3.4 map() —— 映射/批量转换

3.5 reduce() —— 累积计算(需要导入)

3.6 高阶函数全家福

🎯 本章重点速查

🧁 结尾



前言

上回我们把函数的基础讲完了——怎么定义、怎么传参、怎么返回值,还有那个一次性小工具 lambda。函数这块的“地基”你已经打好了。

今天我们往上盖两层楼:

第一层:变量作用域 —— 为什么你在函数里改了一个变量,外面纹丝不动?为什么有时候你死活改不了外面的变量?这就是“作用域”在作怪。弄懂它,你才知道哪些变量在哪儿能用、在哪儿不能动。

第二层:递归函数 —— 函数自己调自己,听起来像俄罗斯套娃?没错,它是解决“重复做同一件事、但每次规模变小”这类问题的终极武器。

第三层:高阶函数 —— 函数不只是被调用的,它还可以被传来传去、当作参数塞给另一个函数。排序、过滤、映射……这些都是高阶函数的地盘。

这三块学完,你手里的函数就像从“小兵”进化成了“法师”——走位灵活、控制力强、还能召唤分身。

开整!🔥

第一章:变量作用域 —— 哪里的地盘哪里说了算

1.1 什么叫“作用域”?

简单说就是:变量在哪个范围内有效

你在函数里面定义的变量,外面访问不到;你在外面定义的变量,函数里面能看见,但不一定能改。这就是作用域在管。

看个例子:

python

name = "全局老王"      # 全局变量

def test():
    name = "局部小李"   # 局部变量
    print("函数内部:", name)

test()                  # 函数内部:局部小李
print("函数外部:", name)  # 函数外部:全局老王

📌 函数里面的 name 和外面的 name 是两个不同的变量,各管各的,互不干扰。就像两个同名同姓的人,一个在A公司上班,一个在B公司上班,互相不串门。

1.2 局部变量 —— 只在函数内部有效

在函数内部定义的变量,叫局部变量,只能在这个函数里面用,函数一结束它就“消失”了。

python

def greet():
    msg = "你好呀"   # 局部变量
    print(msg)

greet()              # 你好呀
# print(msg)         # ❌ 报错!NameError: name 'msg' is not defined

💡 局部变量就像一个工位上的笔记本——你在工位上随便写随便用,但你离开工位,这个本子别人就拿不到了。

1.3 全局变量 —— 在整个文件都有效

在函数外面(最顶层)定义的变量,叫全局变量,整个文件的所有函数都能看到它。

python

score = 100   # 全局变量

def show_score():
    print("当前分数:", score)   # 函数里能读

show_score()   # 当前分数:100

1.4 在函数里想改全局变量?用 global

函数里可以读取全局变量,但想修改它,必须先声明 global

python

count = 0   # 全局变量

def add_one():
    global count   # 👈 声明:我要改全局的 count
    count += 1

add_one()
add_one()
print(count)   # 2

如果不加 global 会怎样?

python

count = 0

def add_one():
    count += 1   # ❌ UnboundLocalError

⚠️ 为什么会报错?因为 Python 看到你在函数里对 count 做了赋值操作,就默认把它当成局部变量,但你又没给它初始值,所以报错。global 就是在告诉 Python:“别瞎猜了,这个变量是全局的!”

1.5 函数嵌套 + nonlocal —— 跨层修改

函数里面还能再定义函数,这叫嵌套函数

python

def outer():
    x = 10   # 外层函数的局部变量

    def inner():
        nonlocal x   # 👈 我要改外层函数的 x
        x += 5
        print("inner里面:", x)

    inner()
    print("outer里面:", x)

outer()

输出:

text

inner里面:15
outer里面:15

📌 nonlocal 就像“越级上报”——不直接动全局,而是动上一层函数里的变量。适合闭包场景,暂时了解一下就行。

1.6 作用域规则总结

作用域在哪里谁能用怎么声明
局部函数内部只能这个函数用直接 x = 10
全局整个文件所有函数都能读在函数外定义
全局修改在函数里改全局加 global x
外层变量嵌套函数内层函数能用内层加 nonlocal x

第二章:递归函数 —— 自己喊自己

2.1 什么是递归?

递归函数就是在函数内部调用自己的函数。

听起来很绕?举个例子:你站在一面镜子前,镜子里反射出你,那个你又反射出另一个你……无限套娃。

递归的核心逻辑是:把一个大问题拆成一个小问题,小问题再拆成更小的问题,直到小到可以直接解决为止

python

def countdown(n):
    if n <= 0:
        print("🎉 发射!")
        return
    print(n)
    countdown(n - 1)   # 自己调自己

countdown(5)

输出:

text

5
4
3
2
1
🎉 发射!

2.2 递归的两个关键要素

要素一:递归条件 —— 什么时候继续调用自己。

要素二:终止条件 —— 什么时候停下来(不然会无限递归,程序崩溃)。

python

def countdown(n):
    if n <= 0:          # 👈 终止条件:到底了,停下
        print("🎉 发射!")
        return
    print(n)            # 执行当前任务
    countdown(n - 1)    # 👈 递归条件:继续喊自己,但 n 变小了

2.3 经典递归:阶乘

阶乘的数学定义:n! = n × (n-1) × (n-2) × ... × 1

python

def factorial(n):
    if n <= 1:          # 终止条件:1! = 1
        return 1
    return n * factorial(n - 1)   # 递归:n! = n × (n-1)!

print(factorial(5))   # 120

执行过程:

text

factorial(5) = 5 * factorial(4)
             = 5 * 4 * factorial(3)
             = 5 * 4 * 3 * factorial(2)
             = 5 * 4 * 3 * 2 * factorial(1)
             = 5 * 4 * 3 * 2 * 1
             = 120

2.4 经典递归:斐波那契数列

斐波那契:1, 1, 2, 3, 5, 8, 13, 21, 34...(每一项是前两项之和)

python

def fib(n):
    if n <= 2:          # 终止条件:前两项都是 1
        return 1
    return fib(n - 1) + fib(n - 2)   # 当前项 = 前两项之和

print(fib(6))   # 8

⚠️ 斐波那契递归虽然好理解,但效率极低(重复计算太多),实际工作中更多用循环。递归适合那种“问题天然能拆成子问题”的场景,比如遍历文件夹树。

2.5 递归注意事项

要点说明
必须有终止条件没终止条件会无限递归,程序直接炸
递归深度有限Python 默认递归深度约 1000 层,太深会报 RecursionError
能迭代就别递归递归优雅但费内存,小规模用递归,大规模用循环

第三章:高阶函数 —— 函数也可以“被传来传去”

3.1 什么是高阶函数?

在 Python 里,函数和数字、字符串一样,也是对象。这就意味着:

        函数可以赋值给变量

        函数可以作为参数传给另一个函数

        函数可以作为返回值返回

把函数当成参数传来传去,就是高阶函数。就像你点外卖的时候,把“不要香菜”这个指令传给了商家。

python

# 普通函数:接收一个数字
def square(x):
    return x ** 2

# 高阶函数:接收另一个函数作为参数
def process_data(data, func):
    result = []
    for item in data:
        result.append(func(item))
    return result

nums = [1, 2, 3, 4, 5]
print(process_data(nums, square))   # [1, 4, 9, 16, 25]

3.2 sorted() —— 自定义排序规则

sorted() 可以接收 key 参数,指定用哪个字段来排序——这就是高阶函数的典型应用。

python

students = [
    {"name": "王小明", "score": 85},
    {"name": "小红", "score": 92},
    {"name": "小刚", "score": 78}
]

# 按分数排序(升序)
sorted_by_score = sorted(students, key=lambda x: x["score"])
print(sorted_by_score)
# [{'name': '小刚', 'score': 78}, {'name': '王小明', 'score': 85}, {'name': '小红', 'score': 92}]

3.3 filter() —— 筛选数据

filter() 接收一个判断函数和一个可迭代对象,返回满足条件的元素。

python

nums = [1, 2, 3, 4, 5, 6, 7, 8, 9]

# 筛选偶数
even_nums = list(filter(lambda x: x % 2 == 0, nums))
print(even_nums)   # [2, 4, 6, 8]

# 筛选分数 >= 80 的学生
students = [
    {"name": "王小明", "score": 85},
    {"name": "小红", "score": 92},
    {"name": "小刚", "score": 78}
]

top = list(filter(lambda s: s["score"] >= 80, students))
print(top)   # [{'name': '王小明', 'score': 85}, {'name': '小红', 'score': 92}]

3.4 map() —— 映射/批量转换

map() 接收一个转换函数和一个可迭代对象,把每个元素都应用一遍函数,批量加工。

python

nums = [1, 2, 3, 4, 5]

# 每个数字平方
squared = list(map(lambda x: x ** 2, nums))
print(squared)   # [1, 4, 9, 16, 25]

# 用户名字全部转大写
names = ["alice", "bob", "charlie"]
upper_names = list(map(lambda x: x.upper(), names))
print(upper_names)   # ['ALICE', 'BOB', 'CHARLIE']

3.5 reduce() —— 累积计算(需要导入)

reduce() 在 functools 模块里,它会把结果不断累积,最后得出一个最终值。

python

from functools import reduce

nums = [1, 2, 3, 4, 5]

# 累积求和
total = reduce(lambda a, b: a + b, nums)
print(total)   # 15

# 累积求乘积
product = reduce(lambda a, b: a * b, nums)
print(product)   # 120

3.6 高阶函数全家福

函数作用返回值
sorted(数据, key=规则)按规则排序新列表
filter(规则, 数据)筛选符合条件的迭代器(可用 list() 转)
map(规则, 数据)批量转换每个元素迭代器(可用 list() 转)
reduce(规则, 数据)累积计算,得出一个值单个值

🎯 本章重点速查

概念核心要点
局部变量函数内部定义,只在函数内有效
全局变量函数外定义,整个文件可读
global在函数里修改全局变量时声明
nonlocal嵌套函数中修改外层局部变量
递归函数自己调自己,必须有终止条件
高阶函数把函数当参数传来传去
sorted()自定义排序规则
filter()筛选符合条件的元素
map()批量转换每个元素
reduce()累积计算出一个最终值

🧁 结尾

到今天为止,你手里的函数已经从“刚出厂的小兵”进化成了“满级法师”——

作用域让你知道变量在哪儿能用、在哪儿不能动,像法师的技能范围,放对了有效果,放错了就炸自己。

递归让你的代码具备“分身术”,遇到能拆解的问题直接自我复制,层层击破,像法师的分身技能。

高阶函数让你把函数当棋子一样传来传去、组合使用,排序、筛选、映射一条龙,像法师的连招技能。

这三种能力合在一起,你手里已经攒了一套完整的代码组织体系。以后遇到稍微复杂一点的需求,你脑子里会先浮现出“这个逻辑能不能拆成一个函数?”“这个操作用 map 是不是更优雅?”“用递归还是用循环?”

高手和普通选手的区别,从来不是谁会的语法多,而是谁在写之前脑子里已经有了“最佳方案”。

下期我们开始搞 面向对象编程(OOP) ,从类到对象,从属性到方法,给代码盖一栋真正的大楼。咱们下期见~ 👋🐍

Logo

Agent 垂直技术社区,欢迎活跃、内容共建。

更多推荐