Python 递归、闭包与装饰器的编程魔法

news2024/12/26 12:02:55

更多资料获取

📚 个人网站:ipengtao.com


在Python编程中,递归、闭包和装饰器是一些强大的工具,它们能够为代码增色不少,提高代码的可读性和灵活性。本文将深入探讨这三种编程魔法的原理和应用,通过丰富的示例代码帮助读者更好地理解和运用这些概念。

递归

1 递归的基本原理

递归是指一个函数在定义中调用自己的情况。了解递归的基本原理是理解其应用的关键。

def factorial(n):
    if n == 0 or n == 1:
        return 1
    else:
        return n * factorial(n-1)

2 递归的应用场景

递归常用于解决可以分解为相似子问题的问题,例如阶乘、斐波那契数列等。

def fibonacci(n):
    if n <= 0:
        return []
    elif n == 1:
        return [0]
    elif n == 2:
        return [0, 1]
    else:
        fib = fibonacci(n-1)
        fib.append(fib[-1] + fib[-2])
        return fib

闭包

1 闭包的概念

闭包是指一个函数对象,它引用了一些在函数定义体中但是不在参数列表中定义的变量。闭包允许将函数与其环境捆绑在一起。

def outer_function(x):
    def inner_function(y):
        return x + y
    return inner_function

closure = outer_function(10)
print(closure(5))  # 输出:15

2 闭包的应用

闭包常用于保留函数的状态信息,实现一些功能强大的设计模式,例如装饰器。

def multiplier(factor):
    def multiply(x):
        return x * factor
    return multiply

double = multiplier(2)
triple = multiplier(3)

print(double(5))  # 输出:10
print(triple(5))  # 输出:15

装饰器

1 装饰器的定义

装饰器是一种特殊的函数,它可以用来包装其他函数或类,以提供额外的功能。

def my_decorator(func):
    def wrapper():
        print("Something is happening before the function is called.")
        func()
        print("Something is happening after the function is called.")
    return wrapper

@my_decorator
def say_hello():
    print("Hello!")

say_hello()

2 装饰器的常见应用

装饰器常用于日志记录、性能测试、权限验证等方面,为函数添加额外的行为。

import time

def timing_decorator(func):
    def wrapper(*args, **kwargs):
        start_time = time.time()
        result = func(*args, **kwargs)
        end_time = time.time()
        print(f"Function {func.__name__} took {end_time - start_time:.2f} seconds to run.")
        return result
    return wrapper

@timing_decorator
def slow_function():
    time.sleep(2)
    print("Function executed.")

slow_function()

编程魔法的结合应用

1 递归与闭包的结合

递归和闭包的结合常见于解决问题时需要保存状态信息的情形,例如斐波那契数列的优化。

def fibonacci_with_closure(n, memo={}):
    if n <= 0:
        return []
    elif n == 1:
        return [0]
    elif n == 2:
        return [0, 1]
    elif n in memo:
        return memo[n]
    else:
        fib = fibonacci_with_closure(n-1, memo)
        fib.append(fib[-1] + fib[-2])
        memo[n] = fib
        return fib

2 装饰器与递归的结合

装饰器可以用于为递归函数添加一些额外的功能,例如缓存计算结果,提高性能。

def memoize(func):
    cache = {}

    def wrapper(n):
        if n not in cache:
            cache[n] = func(n)
        return cache[n]

    return wrapper

@memoize
def factorial(n):
    if n == 0 or n == 1:
        return 1
    else:
        return n * factorial(n-1)

进阶应用场景

1 递归的进阶应用

递归不仅仅局限于数学问题,还可以应用在其他领域。考虑一个目录结构的遍历:

import os

def list_files(start_path):
    result = []
    for root, dirs, files in os.walk(start_path):
        for file in files:
            result.append(os.path.join(root, file))
    return result

print(list_files('/path/to/directory'))

2 闭包的进阶应用

闭包的灵活性使得它在一些高级应用中大放异彩。考虑一个简单的计数器:

def counter():
    count = 0

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

    return increment

counter1 = counter()
print(counter1())  # 输出:1
print(counter1())  # 输出:2

counter2 = counter()
print(counter2())  # 输出:1

3 装饰器的进阶应用

装饰器在面向切面编程(AOP)中有着广泛的应用,可以用于日志记录、性能分析、事务管理等。

def log_decorator(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_decorator
def add(x, y):
    return x + y

print(add(2, 3))

Python 中的递归、闭包与装饰器:进阶技巧

1 尾递归优化

尾递归是一种特殊的递归形式,在函数的最后一步调用自身。Python并没有对尾递归进行优化,但你可以手动优化:

def factorial_tail_recursive(n, acc=1):
    if n == 0:
        return acc
    else:
        return factorial_tail_recursive(n-1, acc * n)

2 迭代代替递归

在某些情况下,递归可以被迭代替代,以提高性能和减少内存占用:

def factorial_iterative(n):
    result = 1
    for i in range(1, n + 1):
        result *= i
    return result

3 闭包的嵌套

闭包可以嵌套,形成多层嵌套的函数,可以实现更复杂的功能:

def outer_function(x):
    def inner_function(y):
        return x + y
    return inner_function

closure = outer_function(10)
nested_closure = closure(5)
print(nested_closure)  # 输出:15

4 闭包的应用:函数工厂

闭包可以用于创建函数工厂,动态生成函数:

def exponent_factory(power):
    def exponent(x):
        return x ** power
    return exponent

square = exponent_factory(2)
cube = exponent_factory(3)

print(square(5))  # 输出:25
print(cube(5))    # 输出:125

5 带参数的装饰器

装饰器本身也可以接受参数,增加了灵活性:

def repeat(n):
    def decorator(func):
        def wrapper(*args, **kwargs):
            for _ in range(n):
                func(*args, **kwargs)
        return wrapper
    return decorator

@repeat(3)
def say_hello():
    print("Hello!")

# 输出:
# Hello!
# Hello!
# Hello!

6 类装饰器

除了函数,装饰器还可以是类,这样装饰器就可以保存状态:

class TimingDecorator:
    def __init__(self, func):
        self.func = func

    def __call__(self, *args, **kwargs):
        start_time = time.time()
        result = self.func(*args, **kwargs)
        end_time = time.time()
        print(f"Function {self.func.__name__} took {end_time - start_time:.2f} seconds to run.")
        return result

@TimingDecorator
def slow_function():
    time.sleep(2)
    print("Function executed.")

slow_function()

总结

递归、闭包和装饰器是Python编程中的重要概念,它们为代码提供了灵活性和强大的功能。在使用递归时,要确保设置适当的终止条件,避免陷入无限循环,并注意控制递归深度。对于闭包,应该谨慎使用,确保其真正带来代码结构或性能上的优势,并了解变量作用域,避免意外结果。在装饰器的应用中,考虑通用性是关键,使其能够适用于多个函数,同时确保各个装饰器之间没有不必要的冲突。

通过深入理解这些概念,并结合最佳实践和进阶技巧的应用,可以写出更为优雅、高效的代码。适时地运用递归、闭包和装饰器,能够提高代码的可读性、可维护性,同时为解决复杂问题提供了强大的工具。


Python学习路线

在这里插入图片描述

更多资料获取

📚 个人网站:ipengtao.com

如果还想要领取更多更丰富的资料,可以点击文章下方名片,回复【优质资料】,即可获取 全方位学习资料包。

在这里插入图片描述
点击文章下方链接卡片,回复【优质资料】,可直接领取资料大礼包。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1305025.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

JavaScript实现飘窗功能

实现飘窗功能很简单 html代码 <!DOCTYPE html> <html lang"en"><head><meta charset"UTF-8"><meta name"viewport" content"widthdevice-width, initial-scale1.0"><title>Document</title…

Certbot实现 HTTPS 自动续期

Certbot实现 HTTPS 自动续期 以前阿里云支持申请一年的免费https证书&#xff0c;那每年我们手动更新证书并没什么大问题&#xff0c;但现在阿里云的免费证书仅支持3个月&#xff0c;这意味着每三个月都要要申请一下证书显得非常麻烦。 下面我们使用Certbot实现ssl证书的自动…

记录hive/spark取最新且不为null的方法

听标题可能听不懂我想表达的意思&#xff0c;我来描述一下我要做的事&#xff1a; 比如采集同学对某一网站进行数据采集&#xff0c;同一个用户每天会有很多条记录&#xff0c;所以我们要取一条这个用户最新的状态&#xff0c;比如用户改了N次昵称&#xff0c;我们只想得到最后…

kubeadm搭建单master多node的k8s集群--小白文,图文教程

参考文献 K8S基础知识与集群搭建 kubeadm搭建单master多node的k8s集群—主要参考这个博客&#xff0c;但是有坑&#xff0c;故贴出我自己的过程&#xff0c;坑会少很多 注意&#xff1a; 集群配置是&#xff1a;一台master&#xff1a;zabbixagent-k8smaster&#xff0c;两台…

C语言leetcode集训一:数组

为了进一步巩固C语言基础&#xff0c;同时进一步了解leetcode刷题的流程&#xff0c;开始进行C语言的集训&#xff0c;今天是第一天&#xff0c;看看我都做了哪些题&#xff0c;因为周末&#xff0c;有点颓废&#xff0c;所以基本上都是简单题&#xff0c;现在只想睡觉...... 有…

ultralytics yolo图像分类训练案例;pytorch自有数据集图像分类案例

1、ultralytics yolo图像分类训练案例 优点:使用方便,训练过程评估指标可以方便查看 缺点:自带模型少,可选择自定义小 参考:https://docs.ultralytics.com/tasks/classify/#val https://blog.csdn.net/weixin_42357472/article/details/131412851 1)数据集格式 https://…

一文让你认识什么是springboot(创建第一个 SpringBoot 程序)

文章目录 前言1. 环境准备2. Maven3. 第一个 SpringBoot 程序3.1 SpringBoot 介绍3.2 SpringBoot 项⽬创建3.2.1 使用 IDEA 创建3.2.2 网页版创建&#xff08;了解&#xff09; 3.3 项目代码和目录介绍3.3.1 观察pom⽂件3.3.2 父工程3.3.3 目录介绍 3.4 运行项目3.5 输出 Hello…

STM32——串口

串口发送/接收函数&#xff1a; HAL_UART_Transmit(); 串口发送数据&#xff0c;使用超时管理机制 HAL_UART_Receive(); 串口接收数据&#xff0c;使用超时管理机制 HAL_UART_Transmit_IT(); 串口中断模式发送 HAL_UART_Receive_IT(); 串口中断模式接收 HAL_UART_Tran…

线上业务优化之案例实战

本文是我从业多年开发生涯中针对线上业务的处理经验总结而来&#xff0c;这些业务或多或少相信大家都遇到过&#xff0c;因此在这里分享给大家&#xff0c;大家也可以看看是不是遇到过类似场景。本文大纲如下&#xff0c; 后台上传文件 线上后台项目有一个消息推送的功能&#…

thinkphp 使用array_reduce 处理返回的数据格式

我想要的效果&#xff1a; 不使用array_reduce 的效果 &#xff1a; 代码&#xff1a; public function teamList($userId,$good_id){$nowbuyers $this->order->where(good_id,$good_id)->count();$data GroupTotalOrder::alias(t_order)->where(merchant_Id,$u…

每日一题 2454. 下一个更大元素 IV(困难,单调栈)

首先考虑第一大整数问题维护一个单调栈&#xff0c;遍历 nums&#xff0c;弹出栈中所有小于 nums[i] 的数&#xff0c;而 nums[i] 就是这些被弹出的数的第一大整数&#xff0c;知道栈为空或者栈顶元素比 nums[i] 大&#xff0c;证明如下&#xff0c;首先由于是遍历&#xff0c;…

Knowledge Graph知识图谱—9. Knowledge Modeling

9. Knowledge Modeling & Ontology Engineering How should the knowledge in a KG be modeled? – Which classes of entities do we have? – Which relations connect them? – Which constraints hold for them? → these questions are defined in the ontology …

【智能家居】九、停车场车牌识别功能点(回调、解耦)

一、翔云 人工智能开放平台&#xff08;车牌识别&#xff09; 二、cJSON 库 三、实现代码 四、回调函数 五、人脸识别和车牌识别获取数据的区别 六、异步网络请求和同步网络请求的区别 七、解耦 一、翔云 人工智能开放平台&#xff08;车牌识别&#xff09; 翔云 人工智能开放…

vxe-table 右键菜单+权限控制(v3)

1.menu-config 是用于配置右键菜单的属性。通过 menu-config 属性&#xff0c;定义右键菜单的内容、显示方式和样式。 通过 menu-config 属性配置了右键菜单&#xff0c;其中的 options 属性定义了右键菜单的选项。用户在表格中右键点击时&#xff0c;将会弹出包含这些选项的自…

数据库系统原理与实践 笔记 #12

文章目录 数据库系统原理与实践 笔记 #12事务管理和并发控制与恢复(续)并发控制SQL-92中的并发级别基于锁的协议基于锁的协议的隐患锁的授予封锁协议两阶段封锁协议多粒度粒度层次的例子意向锁类型相容性矩阵多粒度封锁模式基于时间戳的协议基于时间戳协议的正确性基于有效性检…

mysql:用SHOW CREATE TABLE tbl_name查看创建表的SQL语句

https://dev.mysql.com/doc/refman/8.2/en/show-create-table.html 可以用SHOW CREATE TABLE tbl_name查看创建表的SQL语句。 例如&#xff0c;SHOW CREATE TABLE test_table;表示查询创建test_table表的SQL语句&#xff1a;

关于电动机智能综合保护器在煤矿内的应用分析-安科瑞 蒋静

摘要 &#xff1a;介绍了矿用电动机智能综合保护器系统的总体结构&#xff0c;采用直接将交流信号整流、滤波、调理、采样的方式变为微控制器能够识别的直流信号&#xff0c;通过对微控制器采集到的直流信号编程判断来实现对电动机的相关保护控制、故障显示与报警以及与上位机的…

Jmeter性能测试:ForEach控制器的用法解析(含视频讲解)

引言 最近我在进行JMeter性能测试时遇到了一些问题&#xff0c;特别是在使用ForEach控制器时感到有点棘手。 但是经过不断地摸索和实践&#xff0c;终于成功地掌握了这个神奇的工具&#xff0c;提高了我的测试效率。因此&#xff0c;今天我想和大家分享我的经验&#xff0c;让…

优思学院|如何建立公司运营指标体系?如何推行六西格玛改进运营指标?

关键绩效指标 (KPI) 是测量您团队或组织朝重要商业目标进展表现如何的量化指标&#xff0c;组织会在多个层面使用 KPI&#xff0c;这视乎您想要追踪何指标而定&#xff0c;您可以设定全组织的、特定团队的、或甚至是个人 KPI。 良好的KPI能让公司管理者掌握组织的营运是否进度…

【(较大规模)作业车间调度JSP】通过OR-Tools的区间变量建模求解的效率对比实验

文章目录 问题描述Python调用OR-Tools建模求解&#xff08;实验一&#xff09;1. 声明问题的模型2. 创建区间变量3. 创建约束条件4. 求解模型5. 基于 plotly 展示甘特图 不同场景下的求解效率对比实验二&#xff1a;工件的工序数有差异实验三&#xff1a;消除工件的加工时长差异…