前言

在 Python 编程中,函数是代码复用的基石。很多初学者虽然会写 def,但往往忽略了文档规范、作用域陷阱以及高阶参数的使用。本文将结合 Python 函数基础与进阶特性,带你系统性地掌握函数编程的核心知识。

第一部分:夯实基础——函数的定义与规范

1. 什么是函数?

函数是组织好的、可重复使用的、用来实现特定功能的代码段。

  • 作用:提高代码的复用性,减少重复代码,提高开发效率。

2. 基础语法与调用

定义函数的标准格式如下:

def function_name(parameters):
    """函数说明文档"""
    # 函数体
    return value
  • 定义:使用 def 关键字,后跟函数名和圆括号。
  • 调用:直接使用 函数名(参数) 即可执行。
  • 接收返回值result = function_name(args)

3. 良好的编程习惯:函数说明文档

给函数添加说明文档(Docstring),能辅助理解函数的作用,特别是在团队协作中非常重要。

格式示例:

def add_num(x, y):
    """
    求和函数
    :param x: 第一个数字
    :param y: 第二个数字
    :return: 两个数字的和
    """
    return x + y
查看文档
print(add_num.doc)

4. 变量的作用域(易错点)

变量并不是在哪里都能用的,这就涉及到了作用域。

  • 局部作用域:函数内部定义的变量,只能在函数内部使用。
  • 全局作用域:函数外部定义的变量,整个文件可用。
  • global 关键字:如果你想在函数内部修改全局变量,必须使用 global 声明。
num = 100  # 全局变量
def test():
global num  # 声明我要用全局的那个 num
num = 200   # 修改全局变量
print(num)
test()
print(num)  # 输出 200,因为被函数修改了

5. 返回值与 None 类型

  • return:不仅结束函数,还将结果返回给调用者。
def add(a, b):
    """返回两个数的和"""
    return a + b
def greet(name):
"""打印问候语,无显式返回值"""
print(f"Hello, {name}!")
# 没有 return 语句,默认返回 None
调用示例
result1 = add(3, 5)  # result1 接收返回值 8
print(result1)        # 输出: 8
result2 = greet("Alice")  # 打印: Hello, Alice!
print(result2)            # 输出: None(函数没有 return)
  • None:表示“空”或“无意义”。
  • 如果函数没有 return,默认返回 None
  • Noneif 判断中相当于 False
  • 常用于变量初始化:result = None

第二部分:函数进阶

掌握了基础后,我们需要让函数变得更灵活、更强大。

6. 函数的嵌套使用

在一个函数内部调用另一个函数。这是封装复杂逻辑的基础。

def func_B():
    print("我是 B 函数")
def func_A():
print("我是 A 函数")
func_B()  # A 里面调用了 B
func_A()

7. 四种参数传递方式(核心重点)

7.1 位置参数

最基础的传参方式。顺序必须一致,个数必须匹配。

def user_info(name, age):
    print(f"姓名: {name}, 年龄: {age}")
user_info("Tom", 20) # 正确
7.2 关键字参数

通过 key=value 形式传递。

  • 作用:消除参数顺序限制,提高代码可读性。
  • 注意:如果混用,位置参数必须在关键字参数前面。
user_info(age=20, name="Tom") # 正确,顺序无所谓

混用示例:

正面示例(正确混用):

def user_info(name, age, city):
    print(f"姓名: {name}, 年龄: {age}, 城市: {city}")
正确:位置参数在前,关键字参数在后
user_info("Tom", city="北京", age=20)  # 输出:姓名: Tom, 年龄: 20, 城市: 北京

反面示例(错误混用):

# 错误:关键字参数在位置参数前面
user_info(name="Tom", "北京", age=20)  # 会报错:SyntaxError: positional argument follows keyword argument

记住这个简单规则:先位置,后关键字。一旦开始使用关键字参数,后面的所有参数都必须使用关键字形式。

7.3 缺省参数(默认参数)

定义函数时给参数一个默认值。调用时如果不传该参数,就使用默认值。

  • 规则:所有位置参数必须出现在缺省参数前面。
def print_info(name, gender="男"):
    print(f"{name} 的性别是 {gender}")
print_info("小明")      # 输出:小明 的性别是 男
print_info("小红", "女") # 输出:小红 的性别是 女
7.4 不定长参数(*args 与 **kwargs)

当你不确定调用者会传入多少个参数时,使用不定长参数。

  • *args:接收所有位置参数,打包成一个元组 (tuple)。
  • **kwargs:接收所有关键字参数,打包成一个字典 (dict)。
*args 单独使用示例

*args 用于接收任意数量的位置参数:

def sum_all(*args):
    """计算所有传入数字的和"""
    total = 0
    for num in args:
        total += num
    return total
调用示例
print(sum_all(1, 2, 3))           # 输出:6
print(sum_all(10, 20, 30, 40))    # 输出:100
print(sum_all(5))                 # 输出:5
print(sum_all())                  # 输出:0(没有参数时,args 是空元组)
**kwargs 单独使用示例

**kwargs 用于接收任意数量的关键字参数:

def print_user_info(**kwargs):
    """打印用户信息"""
    for key, value in kwargs.items():
        print(f"{key}: {value}")
调用示例
print_user_info(name="张三", age=25, city="北京")
输出:
name: 张三
age: 25
city: 北京
print_user_info(title="工程师", department="研发部")
输出:
title: 工程师
department: 研发部
print_user_info()  # 没有参数时,kwargs 是空字典
*args 和 **kwargs 混合使用示例

两者可以同时使用,但必须遵循顺序:*args 在前,**kwargs 在后:

def demo(*args, **kwargs):
    print(f"位置参数打包: {args}")   # 输出元组
    print(f"关键字参数打包: {kwargs}") # 输出字典
demo(1, 2, 3, name="Jack", age=18)
输出:
位置参数打包: (1, 2, 3)
关键字参数打包: {'name': 'Jack', 'age': 18}
demo("a", "b", x=100, y=200)
输出:
位置参数打包: ('a', 'b')
关键字参数打包: {'x': 100, 'y': 200}

重要规则

  • *args 必须放在所有普通位置参数之后
  • **kwargs 必须放在所有参数(包括 *args)之后
  • 正确的参数顺序:普通参数 → *args**kwargs

8. 匿名函数 Lambda

Lambda 是一种极简的函数定义方式,适用于逻辑简单、只需使用一次的场景。

  • 语法lambda 参数: 表达式
  • 特点:只能包含一个表达式,不能包含复杂的语句块,表达式的计算结果就是返回值。
# 普通函数
def add(a, b):
    return a + b
Lambda 写法
sum_func = lambda a, b: a + b
print(sum_func(10, 20)) # 输出 30

应用场景:常作为参数传递给其他高阶函数(如 sort, map, filter)。

students = [('Alice', 88), ('Bob', 95), ('Charlie', 70)]
# 按成绩排序(取元组第二个元素)
students.sort(key=lambda x: x[1])
print(students)

总结

从基础的 def 定义、作用域控制,到进阶的 *args/**kwargs 灵活传参,再到优雅的 lambda 表达式,掌握这些内容,你的 Python 代码将更加简洁、专业且易于维护。建议动手敲一遍代码,体会不同参数传递方式的区别!

更多推荐