4.1函数定义与参数传递

66 阅读4分钟

Python函数参数完全指南:掌握灵活的参数处理艺术

函数参数示意图转存失败,建议直接上传图片文件

def smart_function(a, b=2, *args, c=3, **kwargs):
    """综合参数类型演示"""
    print(f"位置参数: {a}, {b}")
    print(f"默认参数: b={b}, c={c}")
    print(f"可变参数: args={args}")
    print(f"关键字参数: kwargs={kwargs}")
  
# 调用示例
smart_function(1, c=4, 5, d=6)  # 会引发错误吗?

一、参数类型全解析

1. 参数分类与优先级

# 参数定义标准顺序
def standard_order(positional, default=0, *args, kw_only, **kwargs):
    pass

参数类型优先级表

参数类型定义位置调用方式
位置参数函数参数最前必须传入
默认参数位置参数之后可选
可变位置参数*args多余位置参数
关键字参数显式命名参数key=value形式
可变关键字参数**kwargs多余关键字参数

2. 参数传递陷阱与解决方案

# 危险的默认参数
def dangerous_list(value, container=[]):  # 所有调用共享同一个列表
    container.append(value)
    return container

print(dangerous_list(1))  # [1]
print(dangerous_list(2))  # [1,2]

# 安全解决方案
def safe_list(value, container=None):
    if container is None:
        container = []
    container.append(value)
    return container

二、可变参数高级应用

1. *args的魔法

def calculate_average(base, *numbers):
    """计算加权平均数"""
    total = sum(numbers) + base * 2
    return total / (len(numbers) + 2)

# 解包应用
points = [5, 7, 9]
print(calculate_average(3, *points))  # (3*2 +5+7+9)/5 = 6.0

2. **kwargs的威力

def build_profile(name, **attributes):
    """构建用户资料"""
    profile = {
        "name": name,
        "metadata": attributes
    }
    if "age" in attributes:
        profile["birth_year"] = 2023 - attributes["age"]
    return profile

# 字典解包调用
user_info = {"age": 25, "occupation": "Engineer"}
print(build_profile("Alice", **user_info))
# {'name': 'Alice', 'metadata': {'age':25,...}, 'birth_year':1998}

三、函数作为一等公民

1. 高阶函数实践

def data_pipeline(data, *processors):
    """数据处理管道"""
    for processor in processors:
        data = processor(data)
    return data

# 处理函数示例
clean_whitespace = lambda s: re.sub(r'\s+', ' ', s)
remove_punctuation = lambda s: re.sub(r'[^\w\s]', '', s)
capitalize = str.title

text = "hello,  world! this is a TEST."
processed = data_pipeline(text, clean_whitespace, remove_punctuation, capitalize)
# "Hello World This Is A Test"

2. 闭包与工厂函数

def create_counter(initial=0):
    """闭包实现计数器"""
    count = initial
    def increment(step=1):
        nonlocal count
        count += step
        return count
    return increment

timer = create_counter(10)
print(timer())    # 11
print(timer(2))   # 13

函数特性应用场景

  • 回调函数 → GUI事件处理
  • 装饰器 → 功能增强
  • 策略模式 → 算法替换
  • 函数组合 → 数据处理管道

四、参数传递机制解密

1. 对象引用传递

def modify_data(items):
    """展示参数传递本质"""
    print(f"初始内存地址: {id(items)}")
    items.append(4)         # 修改可变对象
    items = [5,6,7]        # 重新绑定引用
    print(f"新内存地址: {id(items)}")

original = [1,2,3]
print(f"原始地址: {id(original)}")
modify_data(original)
print("修改后的原始列表:", original)  # [1,2,3,4]

2. 参数传递示意图

调用前: original → [1,2,3](内存地址0x100)
调用时: items → 0x100
修改后: items → 0x200(重新赋值)
原数据: original → 0x100(内容被修改)

五、企业级最佳实践

1. 类型注解规范

from typing import Callable, Union

def process_data(
    input_data: Union[str, bytes],
    validator: Callable[[str], bool],
    *,
    encoding: str = 'utf-8'
) -> list:
    """带类型注解的规范函数"""
    pass

2. 参数验证装饰器

def validate_args(**validators):
    """参数验证装饰器工厂"""
    def decorator(func):
        def wrapper(*args, **kwargs):
            for name, validator in validators.items():
                value = kwargs.get(name)
                if value and not validator(value):
                    raise ValueError(f"Invalid {name}: {value}")
            return func(*args, **kwargs)
        return wrapper
    return decorator

@validate_args(age=lambda x: x >= 18, email=lambda x: '@' in x)
def register_user(name: str, age: int, email: str):
    pass

六、性能优化技巧

1. 参数解包开销测试

import timeit

def func(a, b, c):
    pass

# 直接调用
t1 = timeit.timeit(lambda: func(1, 2, 3))

# 解包调用
args = (1, 2, 3)
t2 = timeit.timeit(lambda: func(*args))

print(f"直接调用: {t1:.6f}s")
print(f"解包调用: {t2:.6f}s")
# 典型结果:直接调用约0.1μs,解包调用约0.3μs

2. 参数缓存优化

from functools import lru_cache

@lru_cache(maxsize=128)
def heavy_computation(x: int, y: int, *, precision=2):
    # 假设是复杂计算过程
    return round(x ** y, precision)

扩展应用

  • 动态参数解析:实现CLI工具
  • 函数柯里化:创建专用函数
  • 参数依赖注入:构建框架核心
  • 装饰器链:组合多个功能增强
# 柯里化示例
from functools import partial

def power(base, exponent):
    return base ** exponent

square = partial(power, exponent=2)
cube = partial(power, exponent=3)

print(square(5))  # 25
print(cube(3))    # 27

参数处理黄金法则

  1. 优先使用位置参数明确必需参数
  2. 默认参数值应使用不可变类型
  3. *args收集多余位置参数
  4. **kwargs收集多余关键字参数
  5. 关键字参数后于位置参数
  6. 类型注解提升可维护性
  7. 保持参数数量合理(≤5个)

下一步学习

  • 装饰器深度解析
  • 函数式编程模式
  • 元类与参数验证
  • 异步函数参数处理