首页
技术小册
AIGC
面试刷题
技术文章
MAGENTO
云计算
视频课程
源码下载
PDF书籍
「涨薪秘籍」
登录
注册
第 10章 编写高效的函数
10.1 函数名
10.2 函数大小的权衡
10.3 函数的形参和实参
10.3.1 默认参数
10.3.2 使用*和**向函数传参
10.3.3 使用*创建可变参数函数
10.3.4 使用**创建可变参数函数
10.3.5 使用*和**创建包装函数
10.4 函数式编程
10.4.1 副作用
10.4.2 高阶函数
10.4.3 lambda 函数
10.4.4 在列表推导式中进行映射和过滤
10.5 返回值的数据类型应该不变
10.6 抛出异常和返回错误码
第 11章 注释、文档字符串和类型提示
11.1 注释
11.1.1 注释风格
11.1.2 内联注释
11.1.3 说明性的注释
11.1.4 总结性的注释
11.1.5 “经验之谈”的注释
11.1.6 法律注释
11.1.7 注释的专业性
11.1.8 代码标签和TODO 注释
11.1.9 神奇的注释和源文件编码
11.2 文档字符串
11.3 类型提示
11.3.1 使用静态分析器
11.3.2 为多种类型设置类型提示
11.3.3 为列表、字典等设置类型提示
11.3.4 通过注释向后移植类型提示
第 12章 通过Git管理项目
12.1 Git 提交和仓库
12.2 使用Cookiecutter新建Python项目
12.3 安装Git
12.3.1 配置Git 用户名和电子邮件
12.3.2 安装GUI Git 工具
12.4 Git 的工作流程
12.4.1 Git 是如何追踪文件状态的
12.4.2 为什么要暂存文件
12.5 在计算机上创建Git 仓库
12.5.1 添加供Git 追踪的文件
12.5.2 忽略仓库中的文件
12.5.3 提交修改
12.5.4 从仓库中删除文件
12.5.5 重命名和移动仓库中的文件
12.6 查看提交日志
12.7 恢复历史修改
12.7.1 撤销未提交的本地修改
12.7.2 取消暂存的文件
12.7.3 回滚近期的提交
12.7.4 回滚到单个文件的某次提交
12.7.5 重写提交历史
12.8 GitHub 和git推送命令
12.8.1 将一个已存在的仓库推送到GitHub
12.8.2 克隆已存在的GitHub仓库
当前位置:
首页>>
技术小册>>
Python编程轻松进阶(四)
小册名称:Python编程轻松进阶(四)
### 10.3.5 使用`*`和`**`创建包装函数 在Python编程中,函数是组织代码、实现特定功能的基本单元。随着项目复杂度的增加,我们经常会遇到需要修改或增强现有函数功能的情况,而不希望直接修改原始函数代码(这有助于保持代码的模块化和可维护性)。这时,包装函数(也称为装饰器或代理函数)就显得尤为重要。包装函数通过接收一个函数作为参数,并返回一个新的函数,实现了对原函数行为的扩展或修改。在这个过程中,`*`(位置参数解包)和`**`(关键字参数解包)作为Python中的高级特性,为创建灵活且强大的包装函数提供了极大便利。 #### 1. 理解`*`和`**`在函数定义中的使用 在深入探讨如何使用`*`和`**`创建包装函数之前,先简要回顾一下它们在函数定义中的用途。 - `*args`:允许你将一个不定长度的参数列表作为一个元组传递给函数。这意味着,所有没有匹配到具名参数的位置参数都会被收集到`args`这个元组中。 - `**kwargs`:允许你将不定长度的关键字参数作为一个字典传递给函数。这样,所有没有匹配到具名参数的关键字参数都会被收集到`kwargs`这个字典中。 #### 2. 包装函数的基本概念 包装函数是一种特殊的函数,它接收一个或多个函数作为参数,并返回一个新的函数。这个新函数在某些方面对原函数进行了包装或增强,但保留了原函数的基本功能。常见的应用场景包括日志记录、性能测试、权限校验等。 #### 3. 使用`*args`和`**kwargs`创建通用包装函数 当我们想要创建一个能够包装任意函数的包装函数时,`*args`和`**kwargs`变得尤为重要。它们允许包装函数接收并传递任意数量和类型的参数给被包装的函数,从而保证了高度的灵活性和通用性。 ##### 示例:一个简单的日志记录包装函数 假设我们想要创建一个包装函数,用于在调用任何函数之前和之后打印日志信息。这个包装函数需要能够处理任意数量和类型的参数,因为它不知道被包装函数的签名。 ```python def log_wrapper(func): def wrapper(*args, **kwargs): print(f"Calling {func.__name__} with args: {args} and kwargs: {kwargs}") result = func(*args, **kwargs) # 调用原始函数 print(f"{func.__name__} returned: {result}") return result return wrapper # 使用示例 @log_wrapper def add(x, y): return x + y @log_wrapper def greet(name, greeting="Hello"): return f"{greeting}, {name}!" # 调用包装后的函数 print(add(5, 3)) print(greet("Alice")) ``` 在上述示例中,`log_wrapper`是一个包装函数,它接收一个函数`func`作为参数,并返回一个新的函数`wrapper`。`wrapper`函数内部使用了`*args`和`**kwargs`来捕获并传递任意数量和类型的参数给`func`函数。这样,无论`func`的签名如何,`log_wrapper`都能正确地包装它。 #### 4. 进阶:在包装函数中处理特定参数 虽然`*args`和`**kwargs`提供了极大的灵活性,但在某些情况下,我们可能需要在包装函数中处理或修改特定参数。这时,可以结合使用`*args`、`**kwargs`和函数签名中的具名参数来实现。 ##### 示例:带有额外日志级别的包装函数 假设我们想要扩展上述的`log_wrapper`,使其能够接受一个额外的参数`log_level`,用于控制日志的详细程度。 ```python def log_wrapper_with_level(log_level='INFO'): def decorator(func): def wrapper(*args, **kwargs): log_prefix = f"[{log_level}] " print(f"{log_prefix}Calling {func.__name__} with args: {args} and kwargs: {kwargs}") result = func(*args, **kwargs) print(f"{log_prefix}{func.__name__} returned: {result}") return result return wrapper return decorator # 使用示例 @log_wrapper_with_level('DEBUG') def multiply(x, y): return x * y print(multiply(4, 5)) ``` 在这个进阶示例中,`log_wrapper_with_level`首先是一个工厂函数,它接受一个`log_level`参数并返回一个装饰器`decorator`。`decorator`才是真正意义上的包装函数,它接受一个函数`func`并返回一个包装后的函数`wrapper`。通过这种方式,我们既能在包装函数级别控制日志级别,又保留了处理任意数量和类型参数的灵活性。 #### 5. 总结 通过使用`*args`和`**kwargs`,我们可以创建出既灵活又强大的包装函数,这些函数能够接收并传递任意数量和类型的参数给被包装的函数。此外,结合使用函数签名中的具名参数,我们还可以在包装函数中处理或修改特定参数,进一步扩展其功能。包装函数是Python编程中一个非常有用的特性,它能够帮助我们编写更加模块化和可维护的代码。在《Python编程轻松进阶(四)》的后续章节中,我们还将继续探索更多高级编程技巧和最佳实践。
上一篇:
10.3.4 使用**创建可变参数函数
下一篇:
10.4 函数式编程
该分类下的相关小册推荐:
Python编程轻松进阶(二)
Python合辑14-面向对象编程案例(下)
Python合辑8-变量和运算符
Python编程轻松进阶(三)
Python合辑9-判断和循环
Python机器学习基础教程(下)
Python与办公-玩转PPT
Python合辑4-130个字符串操作示例
Python高并发编程与实战
Python机器学习实战
Python爬虫入门与实战开发(上)
机器学习算法原理与实战