Python 函数定义、参数传递与作用域详解
一、函数定义:代码的“工具箱”
函数是将一段代码逻辑封装起来,方便重复使用的工具。用 def
关键字定义,包含名称、参数和代码块。
示例:制作三明治
def make_sandwich(filling, bread="全麦"): # 函数名:make_sandwich,参数:filling(必选),bread(默认值)
"""制作一个三明治,返回描述"""
sandwich = f"{bread}面包夹着{filling}"
return sandwich # 返回结果
# 调用函数
my_sandwich = make_sandwich("火腿", "白面包")
print(my_sandwich) # 输出:白面包夹着火腿
关键点:
- 函数名:自定义名称(如
make_sandwich
)。 - 参数:分为必选参数(
filling
)和默认参数(bread="全麦"
)。 - 返回值:
return
返回结果(若无return
,默认返回None
)。
二、参数传递:传递“钥匙”而非“箱子”
Python 中参数传递本质是传递对象的引用(即“钥匙”)。行为取决于对象是否可变。
1. 不可变对象(数字、字符串、元组)
- 特点:传递的是值的引用,但修改时会创建新对象。
def add_number(num):
num += 10 # 创建新对象,不影响外部变量
print("函数内:", num) # 输出:20
a = 10
add_number(a) # 传递 a 的引用(值为10)
print("函数外:", a) # 输出:10(原值未变)
2. 可变对象(列表、字典、集合)
- 特点:传递的是原对象的引用,直接修改会影响外部。
def add_item(shopping_list):
shopping_list.append("牛奶") # 直接修改原列表
print("函数内:", shopping_list) # 输出:['面包', '牛奶']
my_list = ["面包"]
add_item(my_list)
print("函数外:", my_list) # 输出:['面包', '牛奶']
参数类型总结:
参数类型 | 语法 | 示例 | 用途 |
---|---|---|---|
位置参数 | def func(a, b) | func(1, 2) | 按顺序传递值 |
关键字参数 | func(a=1, b=2) | func(b=2, a=1) | 明确指定参数名,顺序无关 |
默认参数 | def func(a=0) | func() → a=0 | 参数可选,未传递时用默认值 |
可变位置参数 *args | def func(*args) | func(1, 2, 3) → args=(1,2,3) | 接收任意数量的位置参数(元组) |
可变关键字参数 **kwargs | def func(**kwargs) | func(a=1, b=2) → kwargs={'a':1, 'b':2} | 接收任意数量的关键字参数(字典) |
三、作用域:像“房间的可见范围”
想象场景:你家的房子有不同房间,每个房间的东西只能在一定范围内看到。
1. 局部作用域(自己的房间)
- 在函数内部定义的变量,只有自己能用。
def 我的房间():
我的私房钱 = 100 # 只有这个函数内部知道
我的房间()
print(我的私房钱) # 报错!别人找不到这个变量
2. 全局作用域(客厅的公共区域)
- 在函数外面定义的变量,大家都能看到。
客厅的电视 = "大电视"
def 看电视():
print(f"我在看{客厅的电视}") # 能访问客厅的变量
看电视() # 输出:我在看大电视
3. 修改全局变量(在房间里改客厅的东西)
- 如果想在函数内修改全局变量,需要
global
声明。
客厅的存款 = 1000
def 存钱():
global 客厅的存款 # 声明要修改的是客厅的存款
客厅的存款 += 500
存钱()
print(客厅的存款) # 输出:1500
4. 闭包作用域(嵌套函数,像盒子套盒子)
- 外层函数的变量,内层函数可以看,但要修改需要
nonlocal
。
def 外层():
外层的钱包 = 100
def 内层():
nonlocal 外层的钱包 # 声明要修改外层的钱包
外层的钱包 = 50
内层()
print(外层的钱包) # 输出:50
外层()
四、综合练习
代码示例:
a = 100
def func():
a = 200
def inner_func():
nonlocal a
a = 300
inner_func()
print("inner:", a) # 输出:300
func() # 调用函数
print("global:", a) # 输出:100
解析:
a = 100
是全局变量。func()
内a = 200
是闭包作用域变量。inner_func()
使用nonlocal a
修改闭包作用域的a
为 300。- 全局
a
不受影响,仍为 100。
总结表格
概念 | 关键点 |
---|---|
函数定义 | 用 def 定义,支持默认参数、可变参数(*args , **kwargs ) |
参数传递 | 传递对象引用,不可变对象修改创建新对象,可变对象修改直接影响原数据 |
作用域规则 | 按 LEGB 顺序查找变量,global 修改全局变量,nonlocal 修改闭包变量 |
常见错误 | 在函数内未声明直接修改全局变量会创建局部变量,导致预期外的结果 |
通过理解这些核心概念,可以避免常见的编程错误,并编写更清晰、高效的Python代码! 🚀