当前位置: 首页 > news >正文

第12篇:从入门到精通:掌握python高级函数与装饰器

第12篇:高级函数与装饰器

内容简介

本篇文章将深入探讨Python中的高级函数装饰器。您将学习什么是高阶函数,掌握常用的高阶函数如mapfilterreduce的使用方法;理解闭包的概念及其应用;深入了解装饰器的定义与使用,包括装饰器的嵌套与参数化。通过丰富的代码示例,您将能够灵活地运用这些高级功能,提升代码的简洁性和可维护性。


目录

  1. 高级函数概述
    • 什么是高阶函数
    • 常用的高阶函数
  2. 高阶函数的应用
    • map函数
    • filter函数
    • reduce函数
  3. 闭包
    • 闭包的定义
    • 闭包的应用场景
  4. 装饰器
    • 装饰器的定义与基本用法
    • 装饰器的嵌套
    • 参数化装饰器
  5. 示例代码
    • 高阶函数示例
    • map函数示例
    • filter函数示例
    • reduce函数示例
    • 闭包示例
    • 装饰器示例
    • 装饰器嵌套与参数化示例
  6. 常见问题及解决方法
    • 问题1:高阶函数与普通函数的区别是什么?
    • 问题2:如何避免闭包中的变量捕获问题?
    • 问题3:装饰器会影响函数的性能吗?
    • 问题4:如何在装饰器中传递参数?
  7. 总结

高级函数概述

什么是高阶函数

**高阶函数(Higher-Order Function)**是指能够接收函数作为参数,或返回一个函数作为结果的函数。在Python中,函数本身也是一等公民,可以像变量一样被传递和操作,这为高阶函数的实现提供了基础。

常用的高阶函数

Python内置了多个高阶函数,常见的包括:

  • map(function, iterable):对可迭代对象的每个元素应用指定函数,返回一个迭代器。
  • filter(function, iterable):过滤可迭代对象中的元素,返回一个迭代器。
  • reduce(function, iterable[, initializer]):对可迭代对象的元素进行累计操作,返回最终结果(需导入functools模块)。
  • sorted(iterable, key=None, reverse=False):根据指定的键对可迭代对象进行排序,返回一个新的列表。
  • sorted 函数也可以视为高阶函数,因为它接受一个函数作为key参数。

高阶函数的应用

map函数

map函数用于将指定函数应用于可迭代对象的每个元素,返回一个新的迭代器。

语法

map(function, iterable, ...)

示例

def square(x):return x ** 2numbers = [1, 2, 3, 4, 5]
squared = map(square, numbers)
print(list(squared))  # 输出: [1, 4, 9, 16, 25]

filter函数

filter函数用于过滤可迭代对象中的元素,返回一个新的迭代器,包含所有使函数返回True的元素。

语法

filter(function, iterable)

示例

def is_even(x):return x % 2 == 0numbers = [1, 2, 3, 4, 5, 6]
even_numbers = filter(is_even, numbers)
print(list(even_numbers))  # 输出: [2, 4, 6]

reduce函数

reduce函数用于对可迭代对象的元素进行累计操作,返回最终结果。reduce函数在Python 3中不再是内置函数,需要从functools模块导入。

语法

from functools import reduce
reduce(function, iterable[, initializer])

示例

from functools import reducedef add(x, y):return x + ynumbers = [1, 2, 3, 4, 5]
total = reduce(add, numbers)
print(total)  # 输出: 15

闭包

闭包的定义

**闭包(Closure)**是指一个函数对象,即使在其定义的作用域之外,依然可以访问其封闭作用域中的变量。闭包由函数及其相关的引用环境组成。

闭包的应用场景

闭包常用于以下场景:

  • 数据封装:隐藏内部实现细节,只暴露接口。
  • 工厂函数:根据参数生成特定功能的函数。
  • 记忆化(Memoization):缓存函数的计算结果,提高性能。

示例

def make_multiplier(n):def multiplier(x):return x * nreturn multipliertimes3 = make_multiplier(3)
print(times3(5))  # 输出: 15times5 = make_multiplier(5)
print(times5(5))  # 输出: 25

装饰器

装饰器的定义与基本用法

**装饰器(Decorator)**是Python中一种用于扩展函数功能的高级语法。装饰器本质上是一个高阶函数,它接受一个函数作为参数,并返回一个新的函数。

基本语法

def decorator(func):def wrapper(*args, **kwargs):# 执行前操作result = func(*args, **kwargs)# 执行后操作return resultreturn wrapper@decorator
def my_function():pass

示例

def logger(func):def wrapper(*args, **kwargs):print(f"调用函数 {func.__name__} 前")result = func(*args, **kwargs)print(f"调用函数 {func.__name__} 后")return resultreturn wrapper@logger
def greet(name):print(f"Hello, {name}!")greet("Alice")

输出

调用函数 greet 前
Hello, Alice!
调用函数 greet 后

装饰器的嵌套

多个装饰器可以叠加在同一个函数上,从内到外依次应用。

示例

def decorator1(func):def wrapper(*args, **kwargs):print("装饰器1前")result = func(*args, **kwargs)print("装饰器1后")return resultreturn wrapperdef decorator2(func):def wrapper(*args, **kwargs):print("装饰器2前")result = func(*args, **kwargs)print("装饰器2后")return resultreturn wrapper@decorator1
@decorator2
def say_hello():print("Hello!")say_hello()

输出

装饰器1前
装饰器2前
Hello!
装饰器2后
装饰器1后

参数化装饰器

装饰器本身接受参数,可以通过添加一层嵌套函数实现。

示例

def repeat(times):def decorator(func):def wrapper(*args, **kwargs):for _ in range(times):func(*args, **kwargs)return wrapperreturn decorator@repeat(times=3)
def say_hi():print("Hi!")say_hi()

输出

Hi!
Hi!
Hi!

示例代码

高阶函数示例

以下示例展示了如何使用高阶函数将一个函数作为参数传递给另一个函数。

def apply_function(func, value):return func(value)def square(x):return x ** 2result = apply_function(square, 5)
print(result)  # 输出: 25

map函数示例

以下示例展示了如何使用map函数将一个列表中的每个元素平方。

def square(x):return x ** 2numbers = [1, 2, 3, 4, 5]
squared = map(square, numbers)
print(list(squared))  # 输出: [1, 4, 9, 16, 25]

filter函数示例

以下示例展示了如何使用filter函数筛选出列表中的偶数。

def is_even(x):return x % 2 == 0numbers = [1, 2, 3, 4, 5, 6]
even_numbers = filter(is_even, numbers)
print(list(even_numbers))  # 输出: [2, 4, 6]

reduce函数示例

以下示例展示了如何使用reduce函数计算列表中所有元素的和。

from functools import reducedef add(x, y):return x + ynumbers = [1, 2, 3, 4, 5]
total = reduce(add, numbers)
print(total)  # 输出: 15

闭包示例

以下示例展示了如何使用闭包创建一个乘数函数。

def make_multiplier(n):def multiplier(x):return x * nreturn multipliertimes4 = make_multiplier(4)
print(times4(5))  # 输出: 20

装饰器示例

以下示例展示了如何定义和使用一个简单的日志装饰器。

def logger(func):def wrapper(*args, **kwargs):print(f"调用函数 {func.__name__} 前")result = func(*args, **kwargs)print(f"调用函数 {func.__name__} 后")return resultreturn wrapper@logger
def greet(name):print(f"Hello, {name}!")greet("Bob")

输出

调用函数 greet 前
Hello, Bob!
调用函数 greet 后

装饰器嵌套与参数化示例

以下示例展示了如何使用多个装饰器以及参数化装饰器。

def decorator1(func):def wrapper(*args, **kwargs):print("装饰器1开始")result = func(*args, **kwargs)print("装饰器1结束")return resultreturn wrapperdef decorator2(func):def wrapper(*args, **kwargs):print("装饰器2开始")result = func(*args, **kwargs)print("装饰器2结束")return resultreturn wrapperdef repeat(times):def decorator(func):def wrapper(*args, **kwargs):for _ in range(times):func(*args, **kwargs)return wrapperreturn decorator@decorator1
@decorator2
@repeat(times=2)
def say_hello():print("Hello!")say_hello()

输出

装饰器1开始
装饰器2开始
Hello!
Hello!
装饰器2结束
装饰器1结束

常见问题及解决方法

问题1:高阶函数与普通函数的区别是什么?

原因:理解高阶函数与普通函数的区别有助于更好地利用函数式编程的优势。

解决方法

  • 高阶函数:能够接受函数作为参数,或返回一个函数。例如mapfilterreduce
  • 普通函数:不具备接受或返回函数的特性,主要用于执行特定任务。

示例

# 普通函数
def add(a, b):return a + b# 高阶函数
def apply_func(func, x, y):return func(x, y)result = apply_func(add, 5, 3)
print(result)  # 输出: 8

问题2:如何避免闭包中的变量捕获问题?

原因:在闭包中使用循环变量可能导致变量捕获问题,即所有闭包共享同一个变量,导致结果不符合预期。

解决方法

使用默认参数将当前值绑定到闭包中,确保每个闭包拥有独立的变量值。

示例

# 有问题的闭包示例
def create_multipliers():multipliers = []for i in range(5):def multiplier(x):return x * imultipliers.append(multiplier)return multipliersfunctions = create_multipliers()
for f in functions:print(f(2))  # 输出: 8, 8, 8, 8, 8# 修正后的闭包示例
def create_multipliers_fixed():multipliers = []for i in range(5):def multiplier(x, i=i):return x * imultipliers.append(multiplier)return multipliersfunctions_fixed = create_multipliers_fixed()
for f in functions_fixed:print(f(2))  # 输出: 0, 2, 4, 6, 8

问题3:装饰器会影响函数的性能吗?

原因:装饰器在函数调用时增加了额外的包装层,可能会带来微小的性能开销。

解决方法

通常情况下,装饰器带来的性能影响是可以忽略的。但在对性能要求极高的场景下,可以考虑优化装饰器逻辑,或使用更高效的装饰器实现方式。

示例

import timedef timer(func):def wrapper(*args, **kwargs):start = time.time()result = func(*args, **kwargs)end = time.time()print(f"函数 {func.__name__} 执行时间: {end - start} 秒")return resultreturn wrapper@timer
def compute():sum = 0for i in range(1000000):sum += ireturn sumcompute()

问题4:如何在装饰器中传递参数?

原因:有时需要在装饰器中传递参数,以实现更灵活的功能。

解决方法

通过增加一层嵌套函数,使装饰器接受参数。通常装饰器的结构会变为三层嵌套。

示例

def repeat(times):def decorator(func):def wrapper(*args, **kwargs):for _ in range(times):func(*args, **kwargs)return wrapperreturn decorator@repeat(times=3)
def say_hi():print("Hi!")say_hi()

输出

Hi!
Hi!
Hi!

总结

在本篇文章中,我们深入探讨了Python中的高级函数装饰器。通过理解高阶函数的概念及其应用,学习了mapfilterreduce等常用高阶函数的使用方法;掌握了闭包的定义和实际应用场景;详细了解了装饰器的定义、基本用法、装饰器的嵌套与参数化。通过丰富的代码示例,您已经具备了运用这些高级功能来编写简洁、高效和可维护代码的能力。

学习建议

  1. 实践项目:尝试在实际项目中应用高阶函数与装饰器,如数据处理、日志记录、权限验证等场景。
  2. 深入学习函数式编程:探索更多函数式编程的概念,如匿名函数(lambda)、柯里化(Currying)、组合(Composition)等。
  3. 优化装饰器性能:在性能敏感的应用中,学习如何编写高效的装饰器,减少不必要的开销。
  4. 编写文档与测试:为装饰器编写清晰的文档,并编写单元测试,确保其功能的正确性和可靠性。
  5. 参与社区与开源项目:通过参与开源项目,学习他人如何运用高阶函数与装饰器,提升编程技能。
  6. 阅读相关书籍和文档:如《Python编程:从入门到实践》、《Fluent Python》,系统性地提升Python编程能力。

接下来的系列文章将继续深入探讨Python的并发编程与多线程,帮助您进一步掌握Python编程的核心概念和技巧。保持学习的热情,持续实践,您将逐步成为一名优秀的Python开发者!


如果您有任何问题或需要进一步的帮助,请随时在评论区留言或联系相关技术社区。

相关文章:

第12篇:从入门到精通:掌握python高级函数与装饰器

第12篇:高级函数与装饰器 内容简介 本篇文章将深入探讨Python中的高级函数与装饰器。您将学习什么是高阶函数,掌握常用的高阶函数如map、filter、reduce的使用方法;理解闭包的概念及其应用;深入了解装饰器的定义与使用&#xff…...

审计文件标识作为水印打印在pdf页面边角

目录 说明 说明 将审计文件的所需要贴的编码直接作为水印贴在页面四个角落,节省辨别时间 我曾经写过一个给pdf页面四个角落加上文件名水印的python脚本,现在需要加一个图形界面进一步加强其实用性。首先通过路径浏览指定文件路径,先检测该路…...

leetcode416.分割等和子集

给你一个 只包含正整数 的 非空 数组 nums 。请你判断是否可以将这个数组分割成两个子集,使得两个子集的元素和相等。 示例 1: 输入:nums [1,5,11,5] 输出:true 解释:数组可以分割成 [1, 5, 5] 和 [11] 。 示例 2&…...

使用docker-compose安装ELK(elasticsearch,logstash,kibana)并简单使用

首先服务器上需要安装docker已经docker-compose,如果没有,可以参考我之前写的文章进行安装。 https://blog.csdn.net/a_lllk/article/details/143382884?spm1001.2014.3001.5502 1.下载并启动elk容器 先创建一个网关,让所有的容器共用此网…...

深度学习中超参数

深度学习中的超参数(hyperparameters)是决定网络结构的变量(例如隐藏层数量)和决定网络训练方式的变量(例如学习率)。超参数的选择会显著影响训练模型所需的时间,也会影响模型的性能。超参数是在训练开始之前设置的,而不是从数据中学习的参数。超参数是模…...

[JavaScript] 运算符详解

文章目录 算术运算符(Arithmetic Operators)注意事项: 比较运算符(Comparison Operators)注意事项: 逻辑运算符(Logical Operators)短路运算:逻辑运算符的返回值&#xf…...

Hooks 使用规则

Hooks 使用规则 命名规则 Hook 必须 useXxx 格式来命名。 PS:这种命名规则也很易读,简单粗暴 调用位置 Hook 或自定义 Hook ,只能在两个地方被调用 组件内部其他 Hook 内部 组件外部,或一个普通函数中,不能调用…...

Ubuntu 24.04 LTS 安装 Docker Desktop

Docker 简介 Docker 简介和安装Ubuntu上学习使用Docker的详细入门教程Docker 快速入门Ubuntu版(1h速通) Docker 安装 参考 How to Install Docker on Ubuntu 24.04: Step-by-Step Guide。 更新系统和安装依赖 在终端中运行以下命令以确保系统更新并…...

智能创造的幕后推手:AIGC浪潮下看AI训练师如何塑造智能未来

文章目录 一、AIGC时代的算法与模型训练概览二、算法与模型训练的关键环节三、AI训练师的角色与职责四、AI训练师的专业技能与素养五、AIGC算法与模型训练的未来展望《AI训练师手册:算法与模型训练从入门到精通》亮点内容简介作者简介谷建阳 目录 《AI智能化办公&am…...

从 JIRA 数据到可视化洞察:使用 Python 创建自定义图表

引言 在项目管理和软件开发中,JIRA 是最广泛使用的工具之一,尤其是在追踪问题、任务和团队进度方面。对于开发者和团队来说,能够从 JIRA 中提取并分析数据,以便更好地理解项目状态和趋势,至关重要。虽然 JIRA 本身提供…...

【网络原理】万字详解 HTTP 协议

🥰🥰🥰来都来了,不妨点个关注叭! 👉博客主页:欢迎各位大佬!👈 文章目录 1. HTTP 前置知识1.1 HTTP 是什么1.2 HTPP 协议应用场景1.3 HTTP 协议工作过程 2. HTTP 协议格式2.1 fiddler…...

PHP企业IM客服系统

💬 企业IM客服系统——高效沟通,无缝连接的智慧桥梁 🚀 卓越性能,释放无限可能 在瞬息万变的商业环境中,我们深知沟通的力量。因此,基于先进的ThinkPHP5框架与高性能的Swoole扩展,我们匠心独运…...

Linux操作系统的灵魂,深度解析MMU内存管理

在计算机的奇妙世界里,我们每天使用的操作系统看似流畅自如地运行着各类程序,背后实则有着一位默默耕耘的 “幕后英雄”—— 内存管理单元(MMU)。它虽不常被大众所熟知,却掌控着计算机内存的关键命脉,是保障…...

PHP代码审计学习01

目录 两种思路 addslashes函数和magic_quotes_gpc配置: 今天来开php代码审计。 PHP无框架项目SQL注入挖掘技巧。 可以看看小迪老师的学习流程或者说是路线吧。 其中,最下面的代码审计工具推荐用下面两款,fortify,seay。 &…...

《数据思维》之数据可视化_读书笔记

文章目录 系列文章目录前言一、pandas是什么?二、使用步骤 1.引入库2.读入数据总结 前言 数据之道,路漫漫其修远兮,吾将上下而求索。 一、数据可视化 最基础的数据可视化方法就是统计图。一个好的统计图应该满足四个标准:准确、有…...

深度学习常见术语解释

正例与负例: 在分类任务中,通常将目标类别称为正例(positive),非目标类别称为负例(negative)。 True Positives(TP): 被正确地划分为正例的个数,…...

重温STM32之环境安装

缩写 CMSIS:common microcontroller software interface standard 1,keil mdk安装 链接 Keil Product Downloads 安装好后,开始安装平台软件支持包(keil 5后不在默认支持所有的平台软件开发包,需要自行下载&#…...

使用Flask和Pydantic实现参数验证

使用Flask和Pydantic实现参数验证 1 简介 Pydantic是一个用于数据验证和解析的 Python 库,版本2的性能有较大提升,很多框架使用Pydantic做数据校验。 # 官方参考文档 https://docs.pydantic.dev/latest/# Github地址 https://github.com/pydantic/pyd…...

python_在钉钉群@人员发送消息

python_在钉钉群人员发送消息 1、第一种 企业内部机器人群聊实现人接入指南,适用于群机器人接收消息,处理完一系列的动作之后,将消息返回给发消息的人员,同时该人员。 需要在企微后台新建一个自建应用,在自建应用里…...

C语言之装甲车库车辆动态监控辅助记录系统

🌟 嗨,我是LucianaiB! 🌍 总有人间一两风,填我十万八千梦。 🚀 路漫漫其修远兮,吾将上下而求索。 C语言之装甲车库车辆动态监控辅助记录系统 目录 一、前言 1.1 (一)…...

CVPR 2025 MIMO: 支持视觉指代和像素grounding 的医学视觉语言模型

CVPR 2025 | MIMO:支持视觉指代和像素对齐的医学视觉语言模型 论文信息 标题:MIMO: A medical vision language model with visual referring multimodal input and pixel grounding multimodal output作者:Yanyuan Chen, Dexuan Xu, Yu Hu…...

Linux简单的操作

ls ls 查看当前目录 ll 查看详细内容 ls -a 查看所有的内容 ls --help 查看方法文档 pwd pwd 查看当前路径 cd cd 转路径 cd .. 转上一级路径 cd 名 转换路径 …...

dedecms 织梦自定义表单留言增加ajax验证码功能

增加ajax功能模块&#xff0c;用户不点击提交按钮&#xff0c;只要输入框失去焦点&#xff0c;就会提前提示验证码是否正确。 一&#xff0c;模板上增加验证码 <input name"vdcode"id"vdcode" placeholder"请输入验证码" type"text&quo…...

ip子接口配置及删除

配置永久生效的子接口&#xff0c;2个IP 都可以登录你这一台服务器。重启不失效。 永久的 [应用] vi /etc/sysconfig/network-scripts/ifcfg-eth0修改文件内内容 TYPE"Ethernet" BOOTPROTO"none" NAME"eth0" DEVICE"eth0" ONBOOT&q…...

2023赣州旅游投资集团

单选题 1.“不登高山&#xff0c;不知天之高也&#xff1b;不临深溪&#xff0c;不知地之厚也。”这句话说明_____。 A、人的意识具有创造性 B、人的认识是独立于实践之外的 C、实践在认识过程中具有决定作用 D、人的一切知识都是从直接经验中获得的 参考答案: C 本题解…...

蓝桥杯 冶炼金属

原题目链接 &#x1f527; 冶炼金属转换率推测题解 &#x1f4dc; 原题描述 小蓝有一个神奇的炉子用于将普通金属 O O O 冶炼成为一种特殊金属 X X X。这个炉子有一个属性叫转换率 V V V&#xff0c;是一个正整数&#xff0c;表示每 V V V 个普通金属 O O O 可以冶炼出 …...

C#中的CLR属性、依赖属性与附加属性

CLR属性的主要特征 封装性&#xff1a; 隐藏字段的实现细节 提供对字段的受控访问 访问控制&#xff1a; 可单独设置get/set访问器的可见性 可创建只读或只写属性 计算属性&#xff1a; 可以在getter中执行计算逻辑 不需要直接对应一个字段 验证逻辑&#xff1a; 可以…...

08. C#入门系列【类的基本概念】:开启编程世界的奇妙冒险

C#入门系列【类的基本概念】&#xff1a;开启编程世界的奇妙冒险 嘿&#xff0c;各位编程小白探险家&#xff01;欢迎来到 C# 的奇幻大陆&#xff01;今天咱们要深入探索这片大陆上至关重要的 “建筑”—— 类&#xff01;别害怕&#xff0c;跟着我&#xff0c;保准让你轻松搞…...

用 Rust 重写 Linux 内核模块实战:迈向安全内核的新篇章

用 Rust 重写 Linux 内核模块实战&#xff1a;迈向安全内核的新篇章 ​​摘要&#xff1a;​​ 操作系统内核的安全性、稳定性至关重要。传统 Linux 内核模块开发长期依赖于 C 语言&#xff0c;受限于 C 语言本身的内存安全和并发安全问题&#xff0c;开发复杂模块极易引入难以…...

深入解析光敏传感技术:嵌入式仿真平台如何重塑电子工程教学

一、光敏传感技术的物理本质与系统级实现挑战 光敏电阻作为经典的光电传感器件&#xff0c;其工作原理根植于半导体材料的光电导效应。当入射光子能量超过材料带隙宽度时&#xff0c;价带电子受激发跃迁至导带&#xff0c;形成电子-空穴对&#xff0c;导致材料电导率显著提升。…...