理解 Python 函数的基本定义与调用方式
掌握函数参数的多种类型及其使用场景
了解嵌套函数、匿名函数(lambda)和递归函数的特性
明确 Python 中参数传递机制的本质(对象引用传递)
能够编写结构清晰、可复用的函数代码
在 Python 中,函数是一段执行特定任务的代码块。通过将常用或重复的逻辑封装成函数,我们可以避免重复编写相同代码,只需在需要时调用该函数即可,极大提升了代码的可读性与可维护性。
使用 def 关键字定义函数。函数可以接受输入(称为参数),也可以不接受任何参数。
def greet():
print("欢迎来到 CodeLab")上述代码定义了一个名为 greet 的函数,调用时会输出欢迎信息。
定义函数后,通过函数名加括号的方式进行调用:
def greet():
print("欢迎来到 CodeLab")
greet() # 调用函数输出:
欢迎来到 CodeLab函数可以接收参数,并通过 return 语句返回结果。
def even_odd(x):
if x % 2 == 0:
return "偶数"
else:
return "奇数"
print(even_odd(16)) # 输出:偶数
print(even_odd(7)) # 输出:奇数说明:
return语句用于将结果传回调用处。若无return,函数默认返回None。
Python 支持多种参数传递方式,灵活应对不同需求。
当调用函数时未提供某个参数的值,该参数将使用预先设定的默认值。
def introduce(name, age=25):
print(f"姓名: {name}")
print(f"年龄: {age}")
introduce("李明") # 使用默认年龄
introduce("王芳", 30) # 指定年龄输出:
姓名: 李明
年龄: 25
姓名: 王芳
年龄: 30调用函数时通过参数名显式指定值,顺序无关。
def describe(first_name, last_name):
print(first_name, last_name)
describe(first_name="张", last_name="伟")
describe(last_name="伟", first_name="张") # 顺序颠倒仍正确输出:
张 伟
张 伟参数按位置依次赋值,顺序必须严格匹配。
def say_hello(name, greeting):
print(f"{greeting}, 我是 {name}!")
say_hello("小陈", "你好") # 正确
say_hello("你好", "小陈") # 逻辑错误!输出:
你好, 我是 小陈!
小陈, 我是 你好!注意:位置参数顺序错误会导致语义混乱。
当参数数量不确定时,可使用 *args(非关键字参数)和 **kwargs(关键字参数)。
def log_args(*args, **kwargs):
print("非关键字参数 (*args):")
for item in args:
print(item)
print("\n关键字参数 (**kwargs):")
for key, value in kwargs.items():
print(f"{key} = {value}")
log_args('开始', '处理', action='登录', user='admin')输出:
非关键字参数 (*args):
开始
处理
关键字参数 (**kwargs):
action = 登录
user = admin
*args接收任意多个位置参数,打包为元组
**kwargs接收任意多个关键字参数,打包为字典
函数可以在另一个函数内部定义,称为嵌套函数。内部函数可以访问外部函数的变量。
def outer():
message = "我热爱编程"
def inner():
print(message)
inner()
outer()输出:
我热爱编程这种结构常用于封装私有逻辑或实现闭包(closure)。
使用 lambda 关键字创建匿名函数——没有名字的简短函数,通常用于简单操作。
# 普通函数
def cube(x):
return x ** 3
# 匿名函数
cube_lambda = lambda x: x ** 3
print(cube(5)) # 125
print(cube_lambda(5)) # 125适用场景:作为高阶函数(如
map,filter,sorted)的参数。
return 用于结束函数并返回结果。可返回单个值、多个值(自动打包为元组)或 None。
def get_stats(a, b):
return a + b, a * b # 返回两个值
sum_val, product = get_stats(3, 4)
print("和:", sum_val) # 和: 7
print("积:", product) # 积: 12引用传递还是值传递?
Python 中所有变量都是对象的引用。函数参数传递的是对象的引用,行为取决于对象是否可变:
不可变对象(如 int, str, tuple):函数内修改不会影响原变量
可变对象(如 list, dict):函数内修改会影响原对象
# 修改列表(可变)
def modify_list(lst):
lst[0] = 999
my_list = [1, 2, 3]
modify_list(my_list)
print(my_list) # [999, 2, 3]
# 修改整数(不可变)
def modify_int(x):
x = 888
num = 100
modify_int(num)
print(num) # 100(未改变)技术上称为 “传对象引用”
函数调用自身称为递归。必须包含终止条件,否则会无限循环。
def factorial(n):
if n == 0: # 基础情况
return 1
return n * factorial(n - 1) # 递归调用
print(factorial(4)) # 24典型应用:阶乘、斐波那契数列、树遍历等分治问题。
函数通过 def 定义,用 函数名() 调用
参数类型包括:默认参数、关键字参数、位置参数、*args / **kwargs
内部函数可访问外层作用域变量
lambda 用于创建简洁的匿名函数
return 返回结果,支持多值返回
Python 采用“传对象引用”机制,可变对象在函数中可被修改
递归需设置明确的终止条件,防止栈溢出
为什么在使用位置参数时,参数顺序非常重要?能否举一个因顺序错误导致程序逻辑出错的例子?
在什么情况下你会选择使用 *args 和 **kwargs?它们对函数的灵活性有何帮助?
递归函数虽然简洁,但可能存在性能或内存问题。你能想到哪些替代递归的迭代实现方式?