一日一技:8行炫技代码,知识点多得不得了

简介: 一日一技:8行炫技代码,知识点多得不得了

我们今天来看一段炫技代码。它可以把任何能接收两个参数的函数定义成一个特殊的运算符。


例如,我们知道Python里面的range函数,最少可以接收1个参数,最多能够接收3个参数。当只有两个参数的时候,格式为range(开始, 结束),从开始数字到结束数字逐次加1,左闭右开。使用今天的方法,可以把它的写法改为开始 |到| 结束,如下图所示:


1.png


又比如,urllib.parse.urljoin可以把域名和一个相对路径拼接起来: urljoin(域名, 相对路径),我们也可以改写成如下图所示的格式:


2.png


这种炫技有余,实用不足的功能是怎么实现的呢?其实原理非常简单,只有8行代码:


from functools import partial
class Change(object):
    def __init__(self, func):
        self.func = func
    def __or__(self, other):
        return self.func(other)
    def __ror__(self, other):
        self.func = partial(self.func, other)
        return self


这里就涉及到一个盲点和两个真正的知识点。这个盲点就是,你可能以为 |到|是一个字符,但是它是3个字符;你可能会把|拼接|看做一个整体,但是它实际上是3个部分:左边的|拼接和右边的|


我们把空格加上,就很明显了:


3.png


两个真正的知识点,就是__or____ror__这两个魔术方法和偏函数partial。而Change本身就是一个普通的类而已,__or____ror__定义了这个类的实例在左侧遇到|时,右侧遇到|时的具体行为。


我们一个一个来讲。首先是__or__。它定义了实例的右侧遇到|时的具体行为。例如,我们用一个简单的代码来进行测试:


class Test:
    def __init__(self, num):
        self.num = num
    def __or__(self, other):
        print(f'我右边有一个东西,它是:{other}')
x = Test(100)
x | 55


运行效果如下图所示:


4.png


但如果你把竖线放在左边,他就会报错,如下图所示:


5.png


__ror__就是用来定义|在实例左边的时候,它的行为:


6.png


所以,我们最开始的例子中,2 |到| 10,实际上应该理解为:


  1. Change(range)返回的实例


  1. 2 | 到 生成一个中间对象,我们假设它是x


  1. x | 10 生成结果


在我们演示的例子中,2 | 到首先进入了Change类的__ror__方法中:


def __ror__(self, other):
        self.func = partial(self.func, other)
        return self


其中,一开始的self.func就是我们在初始化实例Change(range)时传入的参数range。所以partial(self.func, other)等价于partial(range, 2)。关于偏函数partial,大家可以看我这篇文章:偏函数:在Python中设定默认参数的另一种办法。简单来说,使用偏函数,可以给一个真正的函数传一部分参数,过一会再补剩下的参数。


可能大家在日常的开发者,很少会让一个实例方法返回self。关于这个写法,大家可以看我的这一篇文章:一日一技:在Python里面实现链式调用。也就是说,1 | 到返回的,依然是Change类的一个实例,我们简称它为x。这个实例的属性self.func的值是partial(range, 2)


接下来,x | 10,调用的是__or__方法,于是,此时执行的是partial(range, 2)(10)。偏函数的参数补全了,于是它里面的range真正运行了起来,成为了range(2, 10)


至此,这个Change类我们就解析透了。大家知道,在Python里面,魔术方法是有很多的,如果你不想用|,你还可以用其它的,例如:


7.png


或者:


8.png


或者:


9.png


同时,这个Change类,你甚至可以直接当做装饰器来使用。任何能够接收两个参数的函数,都能使用这个装饰器。例如:


10.png


最后总结一下。大家都知道,我是非常反对在工作代码中炫技的,因为炫技的写法很难读,很难维护。今天这个炫技的方法,虽然我也不推荐大家用在工作中,但是它短短8行代码里面,包含了很多个知识点,这就值得大家玩一玩了。


请关注微信公众号【未闻Code】获取更多精彩文章。

目录
相关文章
|
机器学习/深度学习 数据处理 对象存储
机器学习平台PAI智能标注之文本标注 Quick Start
智能标注(iTAG)是机器学习平台PAI上一款智能化数据标注平台,支持图像、文本、视频、音频等多种数据类型的标注以及多模态的混合标注。智能标注(iTAG)提供了丰富的标注内容组件和题目组件,您可以直接使用平台预置的标注模板,也可以根据自己的场景自定义模板进行数据标注。本文以文本标注为例快速演示该功能的使用,以供参考。
1642 0
机器学习平台PAI智能标注之文本标注 Quick Start
|
前端开发 JavaScript UED
【专栏:HTML与CSS移动端开发篇】移动端触摸事件与手势识别
【4月更文挑战第30天】本文探讨了移动端触摸事件和手势识别在网页开发中的重要性。介绍了基础触摸事件如`touchstart`, `touchmove`, `touchend`, `touchcancel`及相关属性。文章列举了处理触摸事件的方法,包括单点触摸、多点触摸、滑动、长按、捏合缩放、旋转检测和事件代理。建议使用第三方库如Hammer.js简化手势处理,并分享了最佳实践,如避免意外触摸、提供视觉反馈、考虑性能和跨设备测试。理解并有效利用这些技术能提升用户交互体验。
497 7
|
网络协议 Java
一文讲明TCP网络编程、Socket套接字的讲解使用、网络编程案例
这篇文章全面讲解了基于Socket的TCP网络编程,包括Socket基本概念、TCP编程步骤、客户端和服务端的通信过程,并通过具体代码示例展示了客户端与服务端之间的数据通信。同时,还提供了多个案例分析,如客户端发送信息给服务端、客户端发送文件给服务端以及服务端保存文件并返回确认信息给客户端的场景。
一文讲明TCP网络编程、Socket套接字的讲解使用、网络编程案例
|
存储 消息中间件 设计模式
新一代消息中间件—Apache Pulsar
新一代消息中间件—Apache Pulsar
1265 107
|
监控 安全 Java
线程死循环定位与处理:精准定位,妥善处理,预防为先
精准定位死循环,妥善处理问题,编码阶段防风险。
417 0
|
机器学习/深度学习 测试技术 计算机视觉
【YOLOv8改进】DAT(Deformable Attention):可变性注意力 (论文笔记+引入代码)
YOLO目标检测创新改进与实战案例专栏探讨了YOLO的有效改进,包括卷积、主干、注意力和检测头等机制的创新,以及目标检测分割项目的实践。专栏介绍了Deformable Attention Transformer,它解决了Transformer全局感受野带来的问题,通过数据依赖的位置选择、灵活的偏移学习和全局键共享,聚焦相关区域并捕获更多特征。模型在多个基准测试中表现优秀,代码可在GitHub获取。此外,文章还展示了如何在YOLOv8中应用Deformable Attention。
|
关系型数据库 应用服务中间件 数据库
Harbor高可用集群设计及部署(基于离线安装方式二)
基于Harbor离线安装方式的高可用方案设计及部署。
755 0
|
数据采集 存储 传感器
数据采集与处理:连接物联世界的智慧数据之旅
本篇深入研究了物联网中的数据采集与处理,包括数据采集方法与技术,数据预处理与清洗,以及数据存储与管理。我们介绍了常见的数据采集方式,如传感器和摄像头,并通过Python代码示例演示了温度传感器数据的采集。此外,我们讨论了数据的预处理与清洗重要性,并简要介绍了数据存储的不同方式,包括SQLite数据库的使用示例。通过本篇内容,读者将更深入了解如何高效地采集、处理和管理物联网中的智慧数据,为连接智能世界的数据之旅做好准备。
748 0
|
存储 算法 搜索推荐
Java核心知识点整理大全23-笔记
Java核心知识点整理大全23-笔记
74 0
kali linux设置中文方法 汉化教程
有勇气的牛排 官方地址:[https://www.couragesteak.com/article/68](https://www.couragesteak.com/article/68)
kali linux设置中文方法 汉化教程