Veloris.
返回索引
概念基础 2026-02-14

Python函数:def一行搞定,不用声明返回类型,还能返回多个值

4 分钟
1.1k words

Python函数:def一行搞定,不用声明返回类型,还能返回多个值

函数是代码复用的基本单位,是组织代码的核心工具。Python的函数比C语言更灵活,支持默认参数、关键字参数、可变参数等特性。本篇将详细介绍Python函数的定义、调用、参数传递及高级特性。


1. 函数的定义与调用

1.1 基本语法

# 函数定义
def 函数名(参数列表):
    """文档字符串(可选)"""
    函数体
    return 返回值  # 可选

# 示例
def greet(name):
    """向指定的人打招呼"""
    return f"Hello, {name}!"

# 函数调用
message = greet("张三")
print(message)  # Hello, 张三!

# 无参数函数
def say_hello():
    print("Hello, World!")

say_hello()

# 无返回值函数
def print_info(name, age):
    print(f"姓名:{name}")
    print(f"年龄:{age}")

print_info("张三", 25)

1.2 函数文档字符串

def calculate_area(length, width):
    """
    计算矩形面积。
    
    Args:
        length: 矩形的长度
        width: 矩形的宽度
    
    Returns:
        矩形的面积
    
    Raises:
        ValueError: 如果长度或宽度为负数
    
    Example:
        >>> calculate_area(3, 4)
        12
    """
    if length < 0 or width < 0:
        raise ValueError("长度和宽度不能为负数")
    return length * width

# 查看文档
print(calculate_area.__doc__)
help(calculate_area)

1.3 与C语言函数对比

特性C语言Python
返回类型必须声明不需要
参数类型必须声明不需要
默认参数C99支持原生支持
可变参数...和va_list*args, **kwargs
函数重载不支持不支持(但可用默认参数模拟)
返回多值需要指针或结构体直接返回元组
// C语言函数
int add(int a, int b) {
    return a + b;
}
# Python函数
def add(a, b):
    return a + b

2. 函数参数

2.1 位置参数

def greet(name, greeting):
    return f"{greeting}, {name}!"

# 按位置传参
print(greet("张三", "你好"))  # 你好, 张三!

# 参数顺序很重要
print(greet("你好", "张三"))  # 张三, 你好!(顺序错了)

2.2 默认参数

def greet(name, greeting="Hello"):
    return f"{greeting}, {name}!"

# 使用默认值
print(greet("张三"))           # Hello, 张三!
# 覆盖默认值
print(greet("张三", "你好"))   # 你好, 张三!

# 多个默认参数
def create_user(name, age=18, city="北京", active=True):
    return {
        "name": name,
        "age": age,
        "city": city,
        "active": active
    }

print(create_user("张三"))
print(create_user("李四", 25))
print(create_user("王五", city="上海"))

# ⚠️ 注意:默认参数必须在非默认参数之后
# def func(a=1, b):  # SyntaxError
#     pass

2.3 关键字参数

def greet(name, greeting):
    return f"{greeting}, {name}!"

# 使用关键字参数(顺序无关)
print(greet(name="张三", greeting="你好"))
print(greet(greeting="你好", name="张三"))

# 混合使用(位置参数必须在前)
print(greet("张三", greeting="你好"))
# print(greet(name="张三", "你好"))  # SyntaxError

2.4 可变位置参数(*args)

def sum_all(*args):
    """接收任意数量的位置参数"""
    print(f"args类型:{type(args)}")  # <class 'tuple'>
    print(f"args内容:{args}")
    return sum(args)

print(sum_all(1, 2, 3))        # 6
print(sum_all(1, 2, 3, 4, 5))  # 15

# 与普通参数混合
def greet_all(greeting, *names):
    for name in names:
        print(f"{greeting}, {name}!")

greet_all("Hello", "张三", "李四", "王五")

# 解包列表作为参数
numbers = [1, 2, 3, 4, 5]
print(sum_all(*numbers))  # 15

2.5 可变关键字参数(**kwargs)

def print_info(**kwargs):
    """接收任意数量的关键字参数"""
    print(f"kwargs类型:{type(kwargs)}")  # <class 'dict'>
    print(f"kwargs内容:{kwargs}")
    for key, value in kwargs.items():
        print(f"{key}: {value}")

print_info(name="张三", age=25, city="北京")

# 与普通参数混合
def create_profile(name, **extra):
    profile = {"name": name}
    profile.update(extra)
    return profile

print(create_profile("张三", age=25, city="北京"))

# 解包字典作为参数
info = {"age": 25, "city": "北京"}
print(create_profile("张三", **info))

2.6 参数组合

参数的顺序规则:位置参数 → 默认参数 → *args → 关键字参数 → **kwargs

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

func(1, 2)
func(1, 2, 3, 4, 5, d=6, e=7, f=8)

# 实际应用示例
def log(message, *args, level="INFO", **kwargs):
    """灵活的日志函数"""
    formatted = message.format(*args, **kwargs) if args or kwargs else message
    print(f"[{level}] {formatted}")

log("简单消息")
log("用户{}登录", "张三")
log("用户{name}{time}登录", name="张三", time="10:00")
log("错误发生", level="ERROR")

2.7 仅限位置参数和仅限关键字参数

# Python 3.8+:仅限位置参数(/之前)
def greet(name, /, greeting="Hello"):
    return f"{greeting}, {name}!"

greet("张三")           # OK
greet("张三", "你好")   # OK
# greet(name="张三")    # TypeError

# 仅限关键字参数(*之后)
def greet(name, *, greeting="Hello"):
    return f"{greeting}, {name}!"

greet("张三")                    # OK
greet("张三", greeting="你好")   # OK
# greet("张三", "你好")          # TypeError

# 组合使用
def func(pos_only, /, standard, *, kw_only):
    print(pos_only, standard, kw_only)

func(1, 2, kw_only=3)        # OK
func(1, standard=2, kw_only=3)  # OK

3. 返回值

3.1 单个返回值

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

result = add(3, 5)
print(result)  # 8

3.2 多个返回值

# 返回元组(最常用)
def get_min_max(numbers):
    return min(numbers), max(numbers)

min_val, max_val = get_min_max([3, 1, 4, 1, 5, 9])
print(f"最小值:{min_val}, 最大值:{max_val}")

# 返回字典
def analyze_text(text):
    return {
        "length": len(text),
        "words": len(text.split()),
        "chars": len(text.replace(" ", ""))
    }

result = analyze_text("Hello World")
print(result)

# 返回命名元组(更清晰)
from collections import namedtuple

Stats = namedtuple('Stats', ['min', 'max', 'avg'])

def get_stats(numbers):
    return Stats(
        min=min(numbers),
        max=max(numbers),
        avg=sum(numbers) / len(numbers)
    )

stats = get_stats([1, 2, 3, 4, 5])
print(f"最小:{stats.min}, 最大:{stats.max}, 平均:{stats.avg}")

3.3 无返回值

def print_hello():
    print("Hello")
    # 没有return语句

result = print_hello()
print(result)  # None

# 显式返回None
def do_nothing():
    return None

# 提前返回
def check_positive(n):
    if n <= 0:
        return  # 返回None
    print(f"{n}是正数")

4. 变量作用域

4.1 局部变量与全局变量

# 全局变量
global_var = "我是全局变量"

def func():
    # 局部变量
    local_var = "我是局部变量"
    print(global_var)  # 可以读取全局变量
    print(local_var)

func()
print(global_var)
# print(local_var)  # NameError: 局部变量在函数外不可见

4.2 global关键字

counter = 0

def increment():
    global counter  # 声明使用全局变量
    counter += 1

increment()
increment()
print(counter)  # 2

# 不使用global会创建新的局部变量
x = 10

def func():
    x = 20  # 这是新的局部变量,不是全局的x
    print(f"函数内x:{x}")

func()
print(f"全局x:{x}")  # 仍然是10

4.3 nonlocal关键字

def outer():
    x = 10
    
    def inner():
        nonlocal x  # 声明使用外层函数的变量
        x += 1
        print(f"inner中x:{x}")
    
    inner()
    print(f"outer中x:{x}")

outer()
# inner中x:11
# outer中x:11

4.4 LEGB规则

Python查找变量的顺序:Local → Enclosing → Global → Built-in

x = "global"

def outer():
    x = "enclosing"
    
    def inner():
        x = "local"
        print(x)  # local
    
    inner()
    print(x)  # enclosing

outer()
print(x)  # global

# Built-in示例
print(len([1, 2, 3]))  # len是内置函数

# 不要覆盖内置名称
# list = [1, 2, 3]  # 不推荐!会覆盖内置的list

5. Lambda表达式

Lambda是匿名函数,用于创建简单的单行函数。

# 语法:lambda 参数: 表达式

# 基本用法
add = lambda a, b: a + b
print(add(3, 5))  # 8

# 等价于
def add(a, b):
    return a + b

# 常见用途:作为参数传递
numbers = [3, 1, 4, 1, 5, 9, 2, 6]

# 排序
sorted_nums = sorted(numbers)  # 默认升序
sorted_nums = sorted(numbers, key=lambda x: -x)  # 降序

# 按绝对值排序
numbers = [-3, 1, -4, 1, 5, -9]
sorted_nums = sorted(numbers, key=lambda x: abs(x))
print(sorted_nums)  # [1, 1, -3, -4, 5, -9]

# 按字符串长度排序
words = ["apple", "pie", "banana", "cherry"]
sorted_words = sorted(words, key=lambda w: len(w))
print(sorted_words)  # ['pie', 'apple', 'banana', 'cherry']

# 按字典某个键排序
students = [
    {"name": "张三", "score": 85},
    {"name": "李四", "score": 92},
    {"name": "王五", "score": 78}
]
sorted_students = sorted(students, key=lambda s: s["score"], reverse=True)

# 与map、filter配合
numbers = [1, 2, 3, 4, 5]
squares = list(map(lambda x: x**2, numbers))
evens = list(filter(lambda x: x % 2 == 0, numbers))

6. 高阶函数

高阶函数是接收函数作为参数或返回函数的函数。

6.1 函数作为参数

def apply_operation(numbers, operation):
    """对列表中的每个元素应用操作"""
    return [operation(n) for n in numbers]

def square(x):
    return x ** 2

def double(x):
    return x * 2

numbers = [1, 2, 3, 4, 5]
print(apply_operation(numbers, square))  # [1, 4, 9, 16, 25]
print(apply_operation(numbers, double))  # [2, 4, 6, 8, 10]
print(apply_operation(numbers, lambda x: x + 10))  # [11, 12, 13, 14, 15]

6.2 函数作为返回值

def make_multiplier(n):
    """返回一个乘以n的函数"""
    def multiplier(x):
        return x * n
    return multiplier

double = make_multiplier(2)
triple = make_multiplier(3)

print(double(5))  # 10
print(triple(5))  # 15

# 实际应用:创建验证器
def make_validator(min_val, max_val):
    def validator(x):
        return min_val <= x <= max_val
    return validator

is_valid_age = make_validator(0, 150)
is_valid_score = make_validator(0, 100)

print(is_valid_age(25))    # True
print(is_valid_score(150)) # False

6.3 内置高阶函数

numbers = [1, 2, 3, 4, 5]

# map:对每个元素应用函数
squares = list(map(lambda x: x**2, numbers))
print(squares)  # [1, 4, 9, 16, 25]

# filter:过滤元素
evens = list(filter(lambda x: x % 2 == 0, numbers))
print(evens)  # [2, 4]

# reduce:累积计算
from functools import reduce
total = reduce(lambda a, b: a + b, numbers)
print(total)  # 15

product = reduce(lambda a, b: a * b, numbers)
print(product)  # 120

# 更Pythonic的写法(推荐)
squares = [x**2 for x in numbers]
evens = [x for x in numbers if x % 2 == 0]
total = sum(numbers)

7. 闭包

闭包是引用了外部函数变量的内部函数。

def counter():
    count = 0
    
    def increment():
        nonlocal count
        count += 1
        return count
    
    return increment

# 创建计数器
c1 = counter()
c2 = counter()

print(c1())  # 1
print(c1())  # 2
print(c1())  # 3
print(c2())  # 1(独立的计数器)

# 实际应用:缓存
def make_cache():
    cache = {}
    
    def cached_func(n):
        if n not in cache:
            print(f"计算{n}...")
            cache[n] = n ** 2
        return cache[n]
    
    return cached_func

square = make_cache()
print(square(5))  # 计算5... 25
print(square(5))  # 25(直接返回缓存)
print(square(3))  # 计算3... 9

8. 装饰器入门

装饰器是修改函数行为的函数。

# 基本装饰器
def my_decorator(func):
    def wrapper(*args, **kwargs):
        print("函数执行前")
        result = func(*args, **kwargs)
        print("函数执行后")
        return result
    return wrapper

@my_decorator
def say_hello(name):
    print(f"Hello, {name}!")

say_hello("张三")
# 输出:
# 函数执行前
# Hello, 张三!
# 函数执行后

# 等价于
def say_hello(name):
    print(f"Hello, {name}!")
say_hello = my_decorator(say_hello)

# 实用装饰器:计时器
import time

def timer(func):
    def wrapper(*args, **kwargs):
        start = time.time()
        result = func(*args, **kwargs)
        end = time.time()
        print(f"{func.__name__}执行时间:{end - start:.4f}秒")
        return result
    return wrapper

@timer
def slow_function():
    time.sleep(1)
    return "完成"

slow_function()

# 保留原函数信息
from functools import wraps

def my_decorator(func):
    @wraps(func)  # 保留原函数的__name__和__doc__
    def wrapper(*args, **kwargs):
        return func(*args, **kwargs)
    return wrapper

9. 类型提示(Type Hints)

Python 3.5+支持类型提示,提高代码可读性和IDE支持。

# 基本类型提示
def greet(name: str) -> str:
    return f"Hello, {name}!"

def add(a: int, b: int) -> int:
    return a + b

# 复杂类型
from typing import List, Dict, Tuple, Optional, Union

def process_numbers(numbers: List[int]) -> int:
    return sum(numbers)

def get_user(user_id: int) -> Dict[str, str]:
    return {"id": str(user_id), "name": "张三"}

def divide(a: float, b: float) -> Optional[float]:
    """返回除法结果,除数为0时返回None"""
    if b == 0:
        return None
    return a / b

def process(value: Union[int, str]) -> str:
    """接受int或str"""
    return str(value)

# 默认参数
def greet(name: str, greeting: str = "Hello") -> str:
    return f"{greeting}, {name}!"

# 可变参数
def sum_all(*args: int) -> int:
    return sum(args)

# 类型提示不会强制检查,只是提示
result = add("hello", "world")  # 运行时不会报错
# 但IDE和类型检查工具(如mypy)会警告

10. 常见错误与避坑

❌ 错误1:可变默认参数

# 错误:使用可变对象作为默认参数
def add_item(item, lst=[]):
    lst.append(item)
    return lst

print(add_item(1))  # [1]
print(add_item(2))  # [1, 2](不是[2]!)

# 正确:使用None作为默认值
def add_item(item, lst=None):
    if lst is None:
        lst = []
    lst.append(item)
    return lst

❌ 错误2:修改全局变量

# 错误:忘记声明global
counter = 0

def increment():
    counter += 1  # UnboundLocalError
    
# 正确
def increment():
    global counter
    counter += 1

❌ 错误3:返回值被忽略

# 错误:忽略返回值
def process(data):
    return data.upper()

text = "hello"
process(text)  # 返回值被忽略
print(text)    # 仍然是"hello"

# 正确
text = process(text)
print(text)    # "HELLO"

❌ 错误4:参数顺序错误

# 错误:默认参数在非默认参数之前
# def func(a=1, b):  # SyntaxError
#     pass

# 正确
def func(b, a=1):
    pass

11. 实战练习

练习1:实现装饰器

"""
练习:实现一个重试装饰器
"""
import time
from functools import wraps

def retry(max_attempts=3, delay=1):
    def decorator(func):
        @wraps(func)
        def wrapper(*args, **kwargs):
            for attempt in range(1, max_attempts + 1):
                try:
                    return func(*args, **kwargs)
                except Exception as e:
                    print(f"尝试{attempt}失败:{e}")
                    if attempt < max_attempts:
                        time.sleep(delay)
            raise Exception(f"重试{max_attempts}次后仍然失败")
        return wrapper
    return decorator

@retry(max_attempts=3, delay=0.5)
def unstable_function():
    import random
    if random.random() < 0.7:
        raise ValueError("随机错误")
    return "成功"

# result = unstable_function()

练习2:实现缓存装饰器

"""
练习:实现一个简单的缓存装饰器
"""
from functools import wraps

def cache(func):
    cached_results = {}
    
    @wraps(func)
    def wrapper(*args):
        if args not in cached_results:
            cached_results[args] = func(*args)
        return cached_results[args]
    
    return wrapper

@cache
def fibonacci(n):
    if n < 2:
        return n
    return fibonacci(n - 1) + fibonacci(n - 2)

print(fibonacci(100))  # 快速计算

练习3:参数验证

"""
练习:实现参数验证函数
"""
def validate_args(**validators):
    def decorator(func):
        @wraps(func)
        def wrapper(*args, **kwargs):
            # 获取函数参数名
            import inspect
            sig = inspect.signature(func)
            bound = sig.bind(*args, **kwargs)
            bound.apply_defaults()
            
            # 验证参数
            for param_name, validator in validators.items():
                if param_name in bound.arguments:
                    value = bound.arguments[param_name]
                    if not validator(value):
                        raise ValueError(f"参数{param_name}验证失败:{value}")
            
            return func(*args, **kwargs)
        return wrapper
    return decorator

@validate_args(
    age=lambda x: 0 <= x <= 150,
    name=lambda x: len(x) > 0
)
def create_user(name, age):
    return {"name": name, "age": age}

print(create_user("张三", 25))
# create_user("张三", 200)  # ValueError

12. 总结

🔑 核心要点

知识点要点
函数定义def关键字,冒号,缩进
参数类型位置、默认、*args、**kwargs
返回值可返回多个值(元组)
作用域LEGB规则,global/nonlocal
Lambda匿名函数,单行表达式
高阶函数函数作为参数或返回值
闭包内部函数引用外部变量
装饰器修改函数行为
类型提示提高可读性,IDE支持

✅ 学习检查清单

  • 掌握函数定义和调用
  • 理解各种参数类型
  • 掌握返回多个值的方法
  • 理解变量作用域和LEGB规则
  • 能使用Lambda表达式
  • 了解高阶函数的概念
  • 理解闭包的原理
  • 能编写简单的装饰器

📖 下一步学习

掌握了函数基础后,让我们学习Python的字符串处理:


常见问题 FAQ

💬 Python函数参数是传值还是传引用?

都不是。Python是”传对象引用”。不可变对象(int/str/tuple)表现像传值,可变对象(list/dict)表现像传引用。关键是理解:赋值操作会创建新引用,修改操作会影响原对象。

💬 默认参数用可变对象(如list)会怎样?

这是经典坑!def f(lst=[]):中的默认列表会在多次调用间共享。正确写法是def f(lst=None): lst = lst or []


系列导航

End of file.