Python 函数详解:从基础到进阶,一篇搞定函数核心知识

在 Python 中,函数是代码复用的核心载体,也是实现模块化编程的基础。无论是简单的打印输出,还是复杂的业务逻辑,函数都能将代码封装成可复用的单元。今天这篇文章,我们就来系统梳理 Python 函数的核心知识,从基础概念到进阶用法,帮你彻底搞懂函数。

一、函数的基本概念:什么是函数?

函数是封装了特定逻辑的代码块,它接收输入(可选)、执行操作、返回结果(可选)。简单来说,函数就像一个 “工具”:你给它一些材料(参数),它帮你完成特定任务(逻辑),最后可能还给你一个成品(返回值)。

函数的核心价值在于:

  • 代码复用:一次定义,多次调用,避免重复编写相同逻辑
  • 模块化:将复杂问题拆解为多个函数,每个函数负责单一职责
  • 可维护性:修改函数内部逻辑,不影响调用它的代码

1.1 形参与实参:函数与数据的 “接口”

函数在定义和调用时,涉及两个关键概念:

  • 形参(形式参数):定义函数时声明的参数,是函数接收数据的 “占位符”,用变量名表示。
    例:def add(a, b): 中的 a 和 b 就是形参。

  • 实参(实际参数):调用函数时传入的数据,是形参的 “具体值”。
    例:add(1, 2) 中的 1 和 2 就是实参。

形参和实参的关系:调用函数时,实参会赋值给对应的形参,函数内部通过形参使用这些数据。

二、函数的参数:灵活传递数据的多种方式

Python 函数的参数设计非常灵活,支持多种类型的参数,满足不同场景的需求。

2.1 位置参数:按顺序传递的 “必传参数”

位置参数是最基础的参数类型,必须按定义顺序传递,且不能省略

python

def get_user_info(name, age, gender):
    print(f"姓名:{name},年龄:{age},性别:{gender}")

# 必须按 name→age→gender 的顺序传参
get_user_info("张三", 18, "男")  # 正确:按顺序传递
get_user_info(18, "张三", "男")  # 错误:顺序错误导致数据含义混淆

位置参数的核心是 “顺序”,调用时参数的位置必须与定义时一致。

2.2 默认参数:可传可不传的 “便捷参数”

如果给位置参数设置默认值,它就变成了默认参数。默认参数在调用时可以省略(使用默认值),但必须定义在位置参数之后

python

# 定义:默认参数 gender 放在位置参数 name、age 之后
def get_user_info(name, age, gender="未知"):
    print(f"姓名:{name},年龄:{age},性别:{gender}")

# 调用时可省略默认参数
get_user_info("张三", 18)  # 输出:姓名:张三,年龄:18,性别:未知
get_user_info("李四", 20, "女")  # 输出:姓名:李四,年龄:20,性别:女

注意:默认参数的默认值是 “定义时计算” 的,而非调用时。如果默认值是可变对象(如列表),可能会出现意外结果,建议默认值用不可变对象(如 None、字符串)。

2.3 关键字参数:不依赖顺序的 “明确传递”

调用函数时,通过 “参数名 = 值” 的形式传递数据,称为关键字参数。它的优势是不需要遵守位置顺序,让代码更易读。

python

def get_user_info(name, age, gender):
    print(f"姓名:{name},年龄:{age},性别:{gender}")

# 关键字参数调用,顺序可以打乱
get_user_info(age=18, name="张三", gender="男")  # 正确

关键字参数可以和位置参数混合使用,但位置参数必须放在关键字参数之前

python

get_user_info("张三", gender="男", age=18)  # 正确:位置参数在前
get_user_info(gender="男", "张三", age=18)  # 错误:位置参数不能在关键字参数后

2.4 强制关键字参数:必须用关键字传递的参数

在定义函数时,用 * 作为分隔符,* 后面的参数就是强制关键字参数—— 调用时必须用关键字传递,否则会报错。

python

def get_user_info(name, *, age, gender):  # * 后面的 age、gender 是强制关键字参数
    print(f"姓名:{name},年龄:{age},性别:{gender}")

get_user_info("张三", age=18, gender="男")  # 正确:用关键字传递
get_user_info("张三", 18, "男")  # 错误:age、gender 未用关键字传递

强制关键字参数的作用是避免参数顺序混淆,尤其适合参数较多的函数。

2.5 不定项参数:接收任意数量的参数

当不确定需要传递多少个参数时,可用不定项参数,分为两种:

2.5.1 不定项位置参数 *args

*args 用于接收0~n 个位置参数,传递后会被打包成一个元组(tuple)。

python

def sum_numbers(*args):
    print("接收的参数:", args)  # args 是元组
    return sum(args)

print(sum_numbers(1, 2, 3))  # 输出:6(args=(1,2,3))
print(sum_numbers())  # 输出:0(args=())

*args 中的 args 是约定俗成的名称,也可以用其他名字(如 *nums),但建议遵循惯例。

2.5.2 不定项关键字参数 **kwargs

**kwargs 用于接收0~n 个关键字参数,传递后会被打包成一个字典(dict)。

python

def print_info(** kwargs):
    print("接收的参数:", kwargs)  # kwargs 是字典
    for key, value in kwargs.items():
        print(f"{key}:{value}")

print_info(name="张三", age=18, gender="男")
# 输出:
# 接收的参数: {'name': '张三', 'age': 18, 'gender': '男'}
# name:张三
# age:18
# gender:男

同样,kwargs 是约定俗成的名称,可自定义(如 **info)。

2.5.3 不定项参数的组合使用

参数定义的完整顺序(从左到右)是:
** 位置参数 → 默认参数 → *args → 强制关键字参数 → kwargs

python

def func(a, b=10, *args, c, **kwargs):
    print(f"a={a}, b={b}, args={args}, c={c}, kwargs={kwargs}")

func(1, 2, 3, 4, c=5, d=6, e=7)
# 输出:a=1, b=2, args=(3,4), c=5, kwargs={'d':6, 'e':7}

三、匿名函数:简洁的 “一次性” 函数

匿名函数是没有名字的函数,用 lambda 关键字定义,适合编写简单的、只使用一次的逻辑。

3.1 匿名函数的语法

python

lambda [参数列表] : 函数体

特点:

  • 函数体只有 1 行代码,不能写多行
  • 若需返回数据,省略 return(函数体会自动返回结果)
  • 没有函数名,通常作为 “临时工具” 使用

3.2 匿名函数 vs 普通函数

类型定义方式复用性适用场景
普通函数def 函数名():复杂逻辑、需要多次调用
匿名函数lambda简单逻辑、临时使用(如参数)

3.3 匿名函数的使用场景

最常见的是作为高阶函数(如 sortedmapfilter)的参数:

python

# 1. 作为 sorted 的排序依据
students = [("张三", 18), ("李四", 16), ("王五", 20)]
# 按年龄排序(用 lambda 提取年龄作为key)
sorted_students = sorted(students, key=lambda x: x[1])
print(sorted_students)  # 输出:[('李四', 16), ('张三', 18), ('王五', 20)]

# 2. 作为 map 的映射逻辑
numbers = [1, 2, 3, 4]
# 计算每个数的平方
squares = list(map(lambda x: x**2, numbers))
print(squares)  # 输出:[1, 4, 9, 16]

四、函数的分类:按参数和返回值划分

根据函数是否有参数、是否有返回值,可分为 5 类,覆盖所有函数场景:

4.1 任务型函数:无参数,无返回值

只执行操作,不接收数据,也不返回结果。

python

def print_welcome():
    print("欢迎使用本系统!")  # 只做一件事:打印欢迎语

4.2 生产型函数:无参数,有返回值

不接收数据,但会生成并返回结果(像 “生产者”)。

python

import random
def get_random_num():
    return random.randint(1, 100)  # 无参数,但返回随机数

4.3 消费型函数:有参数,无返回值

接收数据并处理,但不返回结果(像 “消费者”)。

python

def print_user_name(name):
    print(f"用户名:{name}")  # 接收name,打印后不返回

4.4 功能型函数:有参数,有返回值

接收数据,处理后返回结果(最常用的类型)。

python

def add(a, b):
    return a + b  # 接收a和b,返回和

4.5 断言型函数:返回布尔值的功能型函数

专门用于判断条件,返回 True 或 False,通常作为逻辑判断的依据。

python

def is_adult(age):
    return age >= 18  # 判断是否成年,返回bool

if is_adult(19):
    print("已成年")

五、函数是对象:更灵活的用法

在 Python 中,万物皆对象,函数也不例外。这意味着函数可以:

5.1 赋值给变量

python

def greet():
    print("Hello")

func_var = greet  # 函数赋值给变量
func_var()  # 调用变量(等价于调用greet()),输出:Hello

5.2 作为函数的参数

python

def add(a, b):
    return a + b

def multiply(a, b):
    return a * b

# 高阶函数:接收函数作为参数
def calculate(func, x, y):
    return func(x, y)

print(calculate(add, 2, 3))  # 输出:5(调用add(2,3))
print(calculate(multiply, 2, 3))  # 输出:6(调用multiply(2,3))

5.3 作为函数的返回值

python

def get_operation(operator):
    if operator == "+":
        return lambda a, b: a + b  # 返回匿名函数
    elif operator == "*":
        return lambda a, b: a * b

add_func = get_operation("+")
print(add_func(2, 3))  # 输出:5

六、补充:函数的进阶知识

6.1 函数的返回值细节

  • 函数可以返回任意类型的数据(整数、列表、字典、甚至函数)
  • 若函数没有 return,默认返回 None
  • 用 return 可以提前终止函数(执行到 return 后,后续代码不执行)
  • 可以返回多个值,实际会被打包成元组:

python

def get_name_and_age():
    return "张三", 18  # 等价于 return ("张三", 18)

name, age = get_name_and_age()  # 解包赋值
print(name, age)  # 输出:张三 18

6.2 函数的嵌套

函数内部可以定义另一个函数(嵌套函数),内部函数可以访问外部函数的变量。

python

def outer():
    x = 10
    def inner():
        print(x + 5)  # 访问外部函数的x
    inner()  # 调用内部函数

outer()  # 输出:15

6.3 函数的作用域

变量的可见范围,分为:

  • 局部作用域:函数内部定义的变量,仅在函数内有效
  • 全局作用域:函数外部定义的变量,整个模块有效
  • 嵌套作用域:嵌套函数中,外层函数的变量对内部函数可见

用 global 声明使用全局变量,nonlocal 声明使用嵌套作用域的变量:

python

x = 100  # 全局变量

def func():
    global x  # 声明使用全局x
    x = 200

func()
print(x)  # 输出:200(全局x被修改)

6.4 装饰器:增强函数功能的 “包装器”

装饰器是一种特殊的函数,用于在不修改原函数代码的前提下,增强函数功能(如计时、日志、权限校验)。

python

# 定义一个计时装饰器
def timer(func):
    def wrapper(*args, **kwargs):
        import time
        start = time.time()
        result = func(*args, **kwargs)  # 调用原函数
        end = time.time()
        print(f"函数耗时:{end - start}秒")
        return result
    return wrapper

# 用 @ 语法使用装饰器
@timer
def slow_func():
    time.sleep(1)  # 模拟耗时操作

slow_func()  # 输出:函数耗时:1.00xxx秒

七、总结

函数是 Python 编程的核心,从基础的参数传递到进阶的装饰器,掌握函数的用法能让你的代码更简洁、高效、可维护。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值