柯里化与无参装饰器

ops/2024/10/8 1:59:00/

柯里化

柯里化的概念:柯里化(Currying)在Python中是一种编程技术,它将原本接受多个参数的函数转换为一系列接受单个参数的函数。这种方法以逻辑学家Haskell Curry的名字命名。

简而言之就是将一次函数调用变成先放入一个参数得到的中间函数对象,然后再对中间函数对象进行传参,这样可以将多参数函数变成多个单参数函数。

python">def add(x):def inner(y,z):return x+y+zreturn innerprint(add(1)(2,3))

在第一个例子中,我们先将x传入得到一个带有x参数的函数对象,然后再对这个函数对象继续传入y,z两个参数,柯里化的程度是取决于我们的需要的,我们当然也可以将其分成三个函数,如下图

python">def add(x):def innner(y):def inner_1(z):return x+y+zreturn inner_1return innnerprint(add(1)(2)(3))

 现在,我们对柯里化有了一定了解,但我们该怎么把柯里化和装饰器关联在一起呢?

装饰器

你可以顾名思义,装饰器就是装饰函数用的,函数太单调?我们可以给它加一些功能让它尽可能丰满一些,为了丰富函数,有必要引入柯里化吗,我直接在函数里写不就行了?这就要考虑到代码侵入性问题了,我们将非业务代码(装饰代码)写在函数里,这就产生了业务与非业务代码的纠缠,这不利于后期代码的修改,何况,如果我想为多个函数进行装饰,难道我要一个一个copy过去?这显然不切实际,所以我们运用了函数的思想,把装饰代码封装到一个函数中,然后再将其应用在目标函数上,这实际上是将函数当作参数传入一个函数(高阶函数),而柯里化在其中的作用就是分割,它将装饰函数应用在目标函数然后返回一个装饰过的目标函数,但这个过程不会影响原目标函数,这可能有一些抽象,接下来我们应用实例来说明。

python">def add(x,y):return x+ydef logger(fn):def wrapper(*args,**kwargs):print("{} function is called. {},{}".format(fn.__name__,args,kwargs))ret = fn(*args,**kwargs)return retreturn wrapperadd = logger(add)

我们定义了一个日志修饰函数,这个修饰器的作用就是说明一下目标函数的使用情况,我们使用柯里化将参数分离,这样我们就能不用传入目标函数的参数了,比如说这个add (x,y),如果不使用柯里化,那我们就要传入x,y的值了,但这不是我们注重的部分,我们的目的是将修饰器应用在目标函数上,至于参数是什么,这不是我们考虑的范畴。所以柯里化其实就是把目标函数的参数与目标函数本身分割开,让我们可以更加关注修饰情况。

 

python">add = logger(add)

我们看到这行代码,其实柯里化的意图已经明显了,我们始终需要的就是这行代码,至于其他参数我们暂时不考虑,而这行代码在python中也作为语法糖(修饰器的语法)变换了存在形式。

python中,我们用@来表示修饰函数。

装饰器语法

@标识符

标识符指向一个函数,用一个函数来装饰它下面的函数,logger称为装饰器函数,add称为被装饰或被包装函数

本质上来看,无参数装饰器logger实际上等效为一个参数的函数

无参数装饰器 logger

@logger 会把它下面紧挨着的函数的标识符提上来作为它的实参

如此,我们可以写成:

python">def logger(fn):def wrapper(*args,**kwargs):print("调用前增强功能")print("{} function is called. {},{}".format(fn.__name__,args,kwargs))ret = fn(*args,**kwargs)print("调用后增强功能")return retreturn wrapper@logger
def add(x,y):return x+y
print(add(1,2))

以上,就是无参装饰器的基本内容,下一篇我们将讨论有参装饰器的使用。

 

 


http://www.ppmy.cn/ops/38482.html

相关文章

二分查找向下取整导致的死循环69. x 的平方根

二分查找向下取整导致的死循环 考虑伪题目:从数组arr中查找出目标元素target对应的下标,如果数组中不存在目标元素,找 到第一个元素值小于target的元素的下标。 编写二分查找算法如下: Testvoid testBinarySearch(){int[] arr n…

逻辑回归模型处理考试通过预测

1.逻辑回归方程: 再来看一看该方程对应的图形: 当样本值远大y越接近1,样本值越小y越接近0,以0.5为分界线的两种情况: 这时负样本就是0,正样本就是1,0和1就是我们给样本定义的标签。在考试通过…

.Net WinFrom中DataGridView控件的熟练学习

是一个熟练掌握DataGridView的Demo 1、里边讲述了如果使用DataGridView数据导出到Excel中,以及Excel数据导入到数据中 2、实现了DataGridView复选框批量删除,按钮进入详细信息,按钮删除等功能 3、实现了根据数据的条件不同行显示的颜色不同以…

Java实现NFS文件上传、下载和读取功能的工具类

Java实现NFS文件上传、下载和读取功能的工具类 引言:代码示例一、准备工作二、工具类设计与核心方法三、异常处理与性能优化四、总结 引言: NFS(Network File System)广泛应用于分布式环境的情况下,这里介绍使用Java工…

Edge浏览器的使用心得与深度探索

在这个浏览器大战的时代,Microsoft Edge作为一款重新设计的现代浏览器,自发布以来就备受瞩目。它不仅在速度、兼容性上有了显著提升,还集成了许多创新功能,为用户带来了全新的浏览体验。本文将从个人使用心得出发,深入…

c++多线程2小时速成

简介 c多线程基础需要掌握这三个标准库的使用&#xff1a;std::thread,std::mutex, andstd::async。 1. Hello, world #include <iostream> #include <thread>void hello() { std::cout << "Hello Concurrent World!\n"; }int main() {std::th…

大数据面试题 —— 数据仓库

目录 数据仓库是什么数据仓库和数据库的区别为什么要对数据仓库分层数仓分层&#xff0c;以及每一层的作用维度建模的三种模型范式建模、维度建模维度建模过程&#xff0c;如何确定这些维度 ***维度模型的各个维度之间是怎么聚合的聚合过程的数据倾斜怎么解决&#xff1f;数据质…

设计模式——解释器模式(Interpreter)

解释器模式&#xff08;Interpreter Pattern&#xff09;是一种行为型设计模式&#xff0c;它给定一个语言&#xff0c;定义它的文法的一种表示&#xff0c;并定义一个解释器&#xff0c;该解释器使用该表示来解释语言中的句子。这种模式主要用来描述如何使用面向对象语言构成一…