打卡Python王者归来--第30天

函数局部变量与全局变量
基本概念

局部变量:在函数内部定义的变量,在该函数内部有效,函数执行结束后自动销毁

全局变量:在函数外部定义,作用于整个程序(模块)范围内的变量。可以被函数内部访问,但修改需特别处理。

局部变量管自己,全局变量管大家;函数想改全局时,记得加 global

语法格式
  • 全局变量定义
python 复制代码
# 全局变量
# 在函数外定义
name = "Alice"        # 全局变量
age = 25

def greet():
    print(f"Hello, {name}")  # 可以读取全局变量
  • 局部变量定义
python 复制代码
# 函数内定义
def calculate_area(radius):
    pi = 3.14159     # 局部变量,仅函数内有效
    area = pi * radius ** 2
    return area      # 返回局部变量的计算结果
全局变量与局部变量对比
方面 全局变量 局部变量
定义位置 函数 函数
作用域 整个模块 函数内部
生命周期 程序运行期间 函数调用期间
修改方式 需要用 global 声明 直接赋值即可
是否能修改 不能直接修改(除非声明 global) 可以自由修改
是否共享 是(多个函数共享) 否(仅本函数独占)
是否冲突 与局部同名时会被局部屏蔽 可与全局同名,局部优先
推荐使用 少量常量(如 MAX_SIZE) 大多数变量处理
locals()、globals()和nonlocal 变量

1、locals() ------ 当前作用域的局部变量字典

  • 返回一个字典,包含当前函数/模块中所有局部变量名和它们的当前值
  • 仅在函数内有效,模块顶层调用也返回全局变量(见下方说明)。
python 复制代码
# 函数内部查看所有局部变量
def calculate_area(radius, height):
    pi = 3.14159
    area = pi * radius ** 2
    volume = area * height
    print("当前局部变量:")
    for k, v in locals().items():
        print(f"  {k} = {v}")
    return volume

calculate_area(5, 10)

2、globals() ------ 全局作用域的变量字典

  • 返回一个字典,包含当前模块中所有全局变量(包括函数、类、变量)。

  • 可用于读取或修改全局变量。

python 复制代码
# 动态修改全局变量
counter = 0
name = "Default"

def update_global_var(var_name, value):
    if var_name in globals():
        globals()[var_name] = value
        print(f"✅ 已更新全局变量 {var_name} = {value}")
    else:
        print(f"❌ 变量 {var_name} 不存在于全局作用域")

update_global_var("counter", 100)
update_global_var("name", "Bob")

print(globals()["counter"])  # 输出:100

3、nonlocal ------ 闭包中引用并修改外层函数的局部变量

  • 声明一个变量不是局部变量,也不是全局变量,而是位于外层嵌套函数的作用域中

  • 用于修改闭包中外部函数的局部变量

python 复制代码
# 防止误改全局变量
# nonlocal 只影响外层函数,不会误改全局!
count = 1000  # 全局变量

def outer():
    count = 10  # 外层局部变量
    def inner():
        nonlocal count  # 指向 outer 的 count
        count += 1
        print(f"inner: count = {count}")
    return inner

inner_func = outer()
inner_func()  # 输出:inner: count = 11
print(f"全局 count: {count}")  # 输出:global count: 1000(未被影响)
综合举例
python 复制代码
# 展示局部变量、全局变量、locals()、globals()、global、nonlocal 的协同应用

# 全局变量(模块级)
counter = 100          # 全局变量
name = "Global"        # 全局变量
debug_mode = True      # 全局配置

print("🚀 程序开始:全局变量初始状态")
print(f"全局 counter = {counter}, name = {name}, debug_mode = {debug_mode}")

# ----------------------------
# 1️⃣ 函数:普通函数,仅读取全局变量
# ----------------------------
def greet_user():
    print("\n--- 1. 普通函数调用 ---")
    greeting = "Hello"            # 局部变量
    print(f"greeting (局部) = {greeting}")
    print(f"读取全局变量 name = {name}")
    print("locals() 中变量:")
    for k, v in locals().items():
        print(f"  {k} => {v}")

greet_user()

# ----------------------------
# 2️⃣ 函数:使用 global 修改全局变量
# ----------------------------
def update_counter():
    global counter  # 声明使用全局变量
    print("\n--- 2. 使用 global 修改全局变量 ---")
    print(f"调用前 counter = {counter}")
    counter = counter + 10
    print(f"调用后 counter = {counter}")
    print("通过 globals() 查看修改结果:")
    print(f"globals()['counter'] = {globals()['counter']}")

update_counter()

# ----------------------------
# 3️⃣ 闭包函数:使用 nonlocal 修改外层函数变量
# ----------------------------
def make_counter():
    count = 0          # 外层函数的局部变量(非全局)
    print(f"\n--- 3. 闭包函数:使用 nonlocal ---")
    print(f"初始化:count = {count}")

    def increment():
        nonlocal count  # 指向 make_counter 中的 count
        count += 1
        print(f"increment 中 count = {count}")
        print("使用 locals() 查看内部局部变量:")
        print(f"  locals() -> {locals()}")

    def get_count():
        return count

    return increment, get_count

# 创建计数器实例
inc, get = make_counter()

print("\n调用计数器:")
inc()  # count=1
inc()  # count=2
print(f"当前 count = {get()}")  # 输出:2

# ----------------------------
# 4️⃣ 模块级:动态修改全局变量(演示 globals() 实用性)
# ----------------------------
def set_config(key, value):
    print("\n--- 4. 动态设置配置(使用 globals())---")
    if key in globals():
        print(f"修改全局变量 {key} 从 {globals()[key]} 到 {value}")
        globals()[key] = value
        print(f"已更新: {key} = {globals()[key]}")
    else:
        print(f"变量 {key} 不存在,跳过")

set_config("debug_mode", False)  # 修改全局配置
print(f"最新 debug_mode = {debug_mode}")

# ----------------------------
# 5️⃣ 最后总结:输出所有变量状态
# ----------------------------
print("\n✅ 程序结束:最终状态")
print(f"全局变量 counter = {counter}")
print(f"全局变量 debug_mode = {debug_mode}")
print(f"全局变量 name = {name}")
print(f" locals() 在模块顶层 = {locals()}")  # 等价于 globals()
匿名函数lambda

lambda 函数是一种小型的匿名函数,使用 lambda 关键字定义。它可以在一行内定义一个简单的函数,无需使用 def 关键字和函数名。

语法格式:

注意事项:只能有一个表达式,不能包含语句(如 print, return

python 复制代码
# 语法格式
lambda arg1[, arg2, arg3,...,argn]:expression
"""
说明
lambda:关键字,表示定义匿名函数
arg1:参数,可以有多个参数,用逗号分隔,也可以没有参数
::冒号分隔参数和表达式
expression:表达式,函数的返回值(只能有一个表达式,不能有多行代码、不能包含语句(如 print, return))
"""
基本应用

匿名函数一般用在不需要函数名称的场合,如一些高阶函数的部分参数是函数,这很适合使用匿名函数。

python 复制代码
# 基本应用 1:基础 lambda 函数 - 两数相加
add_lambda = lambda x, y: x + y
print(f"\n【示例 1】两数相加:5 + 3 = {add_lambda(5, 3)}")

# 基本应用 2:带默认参数的 lambda 函数
power = lambda x, n=2: x ** n
print(f"\n【示例 2】幂次方计算:")
print(f"  5 的平方 = {power(5)}")
print(f"  2 的 4 次方 = {power(2, 4)}")

# 基本应用 3:多参数 lambda 函数
sum_three = lambda a, b, c: a + b + c
print(f"\n【示例 3】三数求和:10 + 20 + 30 = {sum_three(10, 20, 30)}")

# 基本应用 4:return返回值是匿名函数
def func(b):
    return lambda x: 2 * x + b

print(func(5)(10))  # 输出:25
linear1 = func(5)  # 5 将传给lambda 函数的 b
print(linear1(10))  # 10是lambda 函数的 x  输出:25

linear2 = func(3)
print(linear2(10))  # 输出:23

# 匿名函数作为高阶函数的参数
def my_car(cars,func):
    for car in cars:
        print(func(car))

dream_cars = ['bmw', 'audi', 'toyota', 'subaru']
my_car(dream_cars,lambda carbrand:"My dream car is " + carbrand.title())
lambdafilter()map()reduce()、sorted() 的联合应用

1、**lambda + filter()**函数

python 复制代码
# 语法格式
"""
filter(function, iterable)
或
filter(lambda 参数:条件表达式,可迭代对象)
说明:
filter() 用于过滤序列,过滤掉不符合条件的元素,返回由符合条件元素组成的新迭代器
function:判断函数,返回 True 或 False
iterable:可迭代对象(列表、元组等)
"""

# 应用示例
# 筛选特定类型文件
files = [
    {'name': 'report.pdf', 'type': 'pdf'},
    {'name': 'image.jpg', 'type': 'jpg'},
    {'name': 'data.csv', 'type': 'csv'},
    {'name': 'doc.pdf', 'type': 'pdf'},
    {'name': 'photo.png', 'type': 'png'}
]

pdf_files = list(filter(lambda f: f['type'] == 'pdf', files))
print(f"PDF 文件:{[f['name'] for f in pdf_files]}")

2、**lambda + map()**函数

python 复制代码
# 语法格式
"""
map(function, iterable, ...)
或
map(lambda 参数:表达式,可迭代对象)


说明:
map() 对可迭代对象的每个元素应用函数,返回处理结果
function:要对可迭代对象中每个元素应用的函数
iterable:一个或多个可迭代对象
返回处理后的新迭代器
"""

# 案例
# 字符串大写
words = ["hello", "world", "python"]
upper_words = list(map(lambda x: x.upper(), words))
print(f"大写:{upper_words}")  # ['HELLO', 'WORLD', 'PYTHON']

# 多列表对应元素相加
words = ["hello", "world", "python"]
upper_words = list(map(lambda x: x.upper(), words))
print(f"大写:{upper_words}")  # ['HELLO', 'WORLD', 'PYTHON']

# 提取用户邮箱列表
users = [
    {'name': '张三', 'email': 'zhangsan@example.com', 'age': 25},
    {'name': '李四', 'email': 'lisi@example.com', 'age': 30},
    {'name': '王五', 'email': 'wangwu@example.com', 'age': 28}
]

emails = list(map(lambda u: u['email'], users))
print(f"邮箱列表:{emails}")

3、**lambda + reduce()**函数

python 复制代码
# 语法格式
"""
from functools import reduce
reduce(function, iterable[, initializer])
# 或
reduce(lambda 参数 1, 参数 2: 表达式,可迭代对象 [, 初始值])

说明:
reduce() 会对参数序列中元素进行累积操作
function:接收两个参数的函数
iterable:可迭代对象
initializer:可选的初始值
"""

# 示例
# 求和
from functools import reduce
numbers = [1, 2, 3, 4, 5]
product = reduce(lambda x, y: x * y, numbers)
print(f"乘积:{product}")  # 120

# 查找最高分学生
rom functools import reduce

students = [
    {'name': '张三', 'score': 85},
    {'name': '李四', 'score': 92},
    {'name': '王五', 'score': 78},
    {'name': '赵六', 'score': 95}
]

top_student = reduce(lambda x, y: x if x['score'] > y['score'] else y, students)
print(f"最高分学生:{top_student['name']} - {top_student['score']}分")

4、**lambda + sorted()**函数

python 复制代码
# 语法格式
"""
sorted(iterable, key=lambda 参数:表达式,reverse=False/True)

含义和作用:
sorted() 对所有可迭代的对象进行排序操作
iterable:可迭代对象
key:指定用元素的哪个属性或索引进行排序
reverse:排序规则,False 为升序(默认),True 为降序
返回新的已排序列表
"""

# 数字升序排序
numbers = [5, 2, 8, 1, 9, 3]
sorted_numbers = sorted(numbers, key=lambda x: x)
print(f"升序:{sorted_numbers}")  # [1, 2, 3, 5, 8, 9]

# 商品按价格和销量排序
products = [
    {'name': '商品 A', 'price': 100, 'sales': 500},
    {'name': '商品 B', 'price': 50, 'sales': 800},
    {'name': '商品 C', 'price': 100, 'sales': 300},
    {'name': '商品 D', 'price': 80, 'sales': 600}
]

# 按价格升序,价格相同时按销量降序
sorted_products = sorted(products, key=lambda x: (x['price'], -x['sales']))

print("商品排序(价格升序,销量降序):")
for p in sorted_products:
    print(f"  {p['name']}: ¥{p['price']}, 销量:{p['sales']}")
pass与函数

pass 是 Python 中的一个空语句(null statement),它什么也不做,但具有明确的语法意义。在函数中使用 **pass**有其特定的用途和注意事项。

  1. 占位符作用:临时留空函数体

当你正在设计函数结构,但还没想到具体实现时,可以用 pass 占位,避免语法错误。

python 复制代码
def create_database_table():
    """创建数据库表结构(暂未实现)"""
    pass  # TODO: 根据模型生成 SQL
  1. 防止 IndentationError

在 Python 中,函数体不能为空(与 C/Java 不同),必须有缩进的代码块。如果写成下面这样会报错:

python 复制代码
# 报错:IndentationError: expected an indented block
def my_func():
    # 没有代码,会报错!
type关键字应用在函数

type关键字的作用:列出数据的数据类型

python 复制代码
# type关键字在函数中应用
def fun(arg):
    pass


print("列出函数fun的type类型:  ", type(fun))  # <class 'function'>
print("列出匿名函数lambda的type类型:  ", type(lambda x: x))  # <class 'function'>
print("列出内置函数abs的type类型:  ", type(abs))  # <class 'builtin_function_or_method'>
设计自己的range()

我们可以模仿内置 range() 的行为,实现一个自定义版本。

  • 支持 start, stop, step 参数;
  • 返回类似 range 的可迭代对象(使用 yield 实现生成器);
  • 支持正序、倒序、负步长
python 复制代码
# 设计一个my_range()函数
def my_range(start, stop=None, step=1):
    """
    模拟内置 range() 函数行为。
    
    参数:
        start: 起始值 (若无 stop,则作为 stop,start 默认为 0)
        stop: 结束值(不包含)
        step: 步长,默认为 1
    
    返回:生成器对象
    """
    # 处理只有 1 个参数的情况:range(5) -> start=5, stop=None
    if stop is None:
        stop = start
        start = 0

    # 步长不能为 0
    if step == 0:
        raise ValueError("step argument must not be zero")

    # 根据步长决定迭代方向
    if step > 0:
        # 正序:从 start 开始,直到小于 stop
        while start < stop:
            yield start
            start += step
    else:
        # 倒序:从 start 开始,直到大于 stop
        while start > stop:
            yield start
            start += step


# 测试自定义 my_range
print(list(my_range(5)))  # [0, 1, 2, 3, 4]
yield关键字作用及工作原理

yield作用:用来定义一个生成器函数(generator function)------它能"暂停"执行并返回一个值,下次调用时从暂停处继续运行

yield工作原理,当你调用一个使用了 yield 的函数时:

  • 函数不会立即运行;
  • Python 返回一个 生成器对象;
  • 每次调用 next(generator) 或用 for 循环遍历时,函数从上次 yield 位置恢复执行;
  • 执行到下一个 yield 时再次暂停,返回值;
  • 直到函数结束或 return,抛出 StopIteration 异常
yield注意事项
技巧 说明
✅ 生成器是"懒加载" 只有在 next()for 循环时才执行
✅ 不能重复使用已耗尽的生成器 一旦遍历完,就不能再用了
✅ 可以用 list(gen) 转为列表 但会失去"内存节约"优势
✅ 支持 send()throw()(协程) 高级用法,用于交互式生成
❌ 不能对生成器用 len() 因为它可能是无限的
yield与return对比
比较项 return yield
是否暂停
是否可以多次用 是(多次调用 next()
内存使用 高(需保存全部结果) 低(按需生成)
函数返回类型 普通值 生成器对象
是否适合大数/无限序列 ✔️ 是
python 复制代码
# return不能批量输出
def get_numbers():
    for i in range(5):
        return i  # 仅返回第一个值,循环不会继续

print(get_numbers())  # 输出:0

# yield 生成器对象 批量输出
def get_numbers():
    for i in range(5):
        yield i  # 暂停并返回 i,下次调用继续

nums = get_numbers()  # 返回生成器对象,不执行函数体!
print(nums)  # <generator object get_numbers at ...>

# 逐个获取值
print(next(nums))  # 0
print(next(nums))  # 1
print(next(nums))  # 2
装饰器

装饰器(Decorator) 是 Python 中一种高阶函数,用于在不对原函数代码做修改的前提下,动态地为函数添加额外功能。

它本质是:一个接收函数作为参数,并返回一个新函数的函数。

基本语法(使用 @ 语法糖)
python 复制代码
# 装饰器语法格式
@decorator_name
def function_name():
    # 函数逻辑
    pass

等价于:
def function_name():
    # 函数逻辑
    pass

function_name = decorator_name(function_name)
装饰器核心结构(原理)
python 复制代码
"""
说明:
• func:被装饰的原始函数。
• wrapper:包装函数,负责执行额外逻辑 + 调用原函数。
• *args, **kwargs:支持任意参数传递,提升通用性。
"""

def my_decorator(func):
    def wrapper(*args, **kwargs):
        print("函数执行前的操作")
        result = func(*args, **kwargs)
        print("函数执行后的操作")
        return result
    return wrapper

@my_decorator
def say_hello():
    print("Hello!")

say_hello()  
# 输出:
# 函数执行前的操作
# Hello!
# 函数执行后的操作
相关推荐
qq_334903153 小时前
嵌入式C++驱动开发
开发语言·c++·算法
阿贵---3 小时前
C++代码规范化工具
开发语言·c++·算法
2401_831824963 小时前
为你的Python脚本添加图形界面(GUI)
jvm·数据库·python
2401_879693873 小时前
用Pygame开发你的第一个小游戏
jvm·数据库·python
暮冬-  Gentle°3 小时前
自定义内存检测工具
开发语言·c++·算法
一直都在5723 小时前
Java死锁
java·开发语言
娇娇yyyyyy3 小时前
QT编程(15): Qt 按键事件和定时器事件
开发语言·qt
用户0332126663673 小时前
使用 Python 查找并高亮 Word 文档中的文本
python
xushichao19893 小时前
实战:用OpenCV和Python进行人脸识别
jvm·数据库·python