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

更多资料获取

📚 个人网站: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

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

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

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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

040.Python面向对象_设计原则

我 的 个 人 主 页&#xff1a;&#x1f449;&#x1f449; 失心疯的个人主页 &#x1f448;&#x1f448; 入 门 教 程 推 荐 &#xff1a;&#x1f449;&#x1f449; Python零基础入门教程合集 &#x1f448;&#x1f448; 虚 拟 环 境 搭 建 &#xff1a;&#x1f449;&…

【工具栏】idea安装翻译工具

然后重启idea 打开设置 翻译方式&#xff1a; 选中要翻译的文本 然后右键 运行项目的时候&#xff0c;方便查找错误

快速幂+高精乘(填坑)洛谷1226+1045

引言 最近在刷题的时候偶然见到这样一个题目&#xff0c;见下图 大致的意思是&#xff0c;让我们计算a的b次方取模p的结果&#xff0c;再我了解了关于快速幂的内容之后&#xff0c;很快便解决了这道题&#xff0c;每次乘完a后取模最后就可以得到结果。但是在这之后&#xff0c…

淡化了技术指标 还能做现货黄金交易?

技术指标是分析和预测现货黄金走势的其中一种方法&#xff0c;普通投资者多数依赖技术指标为自己的交易做判断。然而&#xff0c;近几年有一种观点认为&#xff0c;我们应该淡化技术指标&#xff0c;少使用或者不用技术分析来服务我们的交易。这个观点引起了不少投资者的思考&a…

NFTScan | 12.04~12.10 NFT 市场热点汇总

欢迎来到由 NFT 基础设施 NFTScan 出品的 NFT 生态热点事件每周汇总。 周期&#xff1a;2023.12.04~ 2023.12.10 NFT Hot News 01/ NFTScan 与 MintCore 联合推出适用于 NFT 的 Layer2 网络 Mint 12 月 5 日&#xff0c;根据官方消息&#xff0c;NFT 基础设施服务商 NFTScan …

Ajax跨域请求

最近使用js构造请求时发生了CORS跨域问题&#xff0c;mark一下 ajax跨域&#xff0c;这应该是最全的解决方案了 | Dailc的个人主页Everything about dailchttps://dailc.github.io/2017/03/22/ajaxCrossDomainSolution.htmlAJAX - 廖雪峰的官方网站研究互联网产品和技术&#…

基于SSM的乡镇篮球队管理系统论文

摘 要 现代经济快节奏发展以及不断完善升级的信息化技术&#xff0c;让传统数据信息的管理升级为软件存储&#xff0c;归纳&#xff0c;集中处理数据信息的管理方式。本乡镇篮球队管理系统就是在这样的大环境下诞生&#xff0c;其可以帮助管理者在短时间内处理完毕庞大的数据信…

华为云CodeArts Artifact:保障制品质量与安全的最佳选择

近期&#xff0c;为降低用户使用成本、满足个性化选择诉求&#xff0c;华为云制品仓库CodeArts Artifact 从软件开发生产线 CodeArtS 解耦出来&#xff0c;可单独购买。这是一款打破了传统制品管理的限制&#xff0c;高效、安全、好用的软件包管理工具。 体验通道&#xff1a;…

独热编码和词向量的简单理解

把单词用向量表示&#xff0c;是把深度神经网络语言模型引入自然语言处理领域的一个核心技术。想要让机器理解单词&#xff0c;就必须要把它变成一串数字&#xff08;向量&#xff09;。下面介绍的 One-Hot Encoding&#xff08;One-Hot 编码&#xff09;和 Word Embedding &am…

接口自动化框架Pytest —— 配置文件pytest.ini的详细使用

前言 我们在执行用例的时候&#xff0c;每次都在命令行中输入-v&#xff0c;-s等一些命令行参数的时&#xff0c;比较麻烦。其中pytest.ini这个配置文件可以快速的帮助我们解决这个问题。 配置文件 pytest.ini文件是pytest的主配置文件&#xff0c;可以改变pytest的运行方式…

Async 异步任务注解类的用法及原理分析

背景 看项目源码发现有一个 Async 注解&#xff0c;它是 Spring 的一个注解&#xff0c;作用是在独立的线程中完成注解方法的操作&#xff0c;底层原理是动态代理。 之前不知道这个知识点&#xff0c;小小测试了一下&#xff0c;发现项目中这个注解的用法是错误的&#xff0c…

Cypress安装与使用教程(2)—— 软测大玩家

&#x1f60f;作者简介&#xff1a;博主是一位测试管理者&#xff0c;同时也是一名对外企业兼职讲师。 &#x1f4e1;主页地址&#xff1a;【Austin_zhai】 &#x1f646;目的与景愿&#xff1a;旨在于能帮助更多的测试行业人员提升软硬技能&#xff0c;分享行业相关最新信息。…

JVM学习笔记-如何在IDEA打印JVM的GC日志信息

若要在Idea上打印JVM相应GC日志&#xff0c;其实只需在Run/Debug Configurations上进行设置即可。 拿《深入Java虚拟机》书中的3-7代码例子来演示&#xff0c;如 1 public class JvmTest {2 private static final int _1MB1024*1024;3 public static void main(String…

AI 技术在前端开发流程中如何应用??3分钟带你一览开放原子开发者大会 OpenTiny 最新资讯!

大会简介 作为开放原子开源基金会的年度盛典&#xff0c;2023 开放原子开发者大会秉持遵循“共建、共治、共享”原则&#xff0c;以“一切为了开发者”为主题。本次大会汇聚顶尖开源人才&#xff0c;共享交流平台&#xff0c;通过吸引和邀请顶尖专家分享见解&#xff0c;设置技…

Leetcode—380.O(1) 时间插入、删除和获取随机元素【中等】

2023每日刷题&#xff08;五十七&#xff09; Leetcode—380.O(1) 时间插入、删除和获取随机元素 算法思想 实现代码 class RandomizedSet { public:vector<int> nums;unordered_map<int, int> dict;RandomizedSet() {srand((unsigned)time(NULL));}bool insert(…

关于核心转储和GDB调试的理解

Linux应用程序发生Segmentation fault段错误时&#xff0c;如何利用core dump文件定位错误呢&#xff1f; 在 Linux 系统中&#xff0c;常将“主内存”称为核心(core)&#xff0c;而核心映像(core image) 就是 “进程”(process)执行当时的内存内容。当进程发生错误或收到“信…

嵌入式系统复习--ARM技术概述

文章目录 上一篇ARM体系结构Thumb技术介绍ARM处理器工作状态ARM的异常响应过程ARM存储器接口及存储器层次下一篇 上一篇 嵌入式系统复习–概述 ARM体系结构 ARM体系结构的技术特征 ARM的体系结构采用了若干Berkeley RISC处理器的特征 Load/store体系结构固定的32为指令3地址…

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

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

C语言leetcode集训一:数组

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

【无标题】树莓派 4B 多串口配置

0. 实验准备以及原理 0.1 实验准备 安装树莓派官方系统的树莓派 4B&#xff0c;有 python 环境&#xff0c;安装了 serial 库 杜邦线若干 屏幕或者可以使用 VNC 进入到树莓派的图形界面 0.2 原理 树莓派 4B 有 UART0&#xff08;PL011&#xff09;、UART1&#xff08;mini UAR…