当前位置: 首页 > 科技观察

一天一技能:8行眼花缭乱的代码,这么多知识点

时间:2023-03-12 04:25:49 科技观察

今天就来看看一段眼花缭乱的代码吧。它将任何接受两个参数的函数定义为特殊运算符。比如我们知道Python中的range函数最少可以接收1个参数,最多可以接收3个参数。当只有两个参数时,格式为range(start,end),从起始号到结束号依次加1,左闭右开。用今天的方法,可以把它的写法改成begin|to|end,如下图:再比如urllib.parse.urljoin可以加入一个域名和一个相对路径:urljoin(domainname,relativepath),我们也可以改写成下图所示的格式:如何实现这种展示技巧绰绰有余但实用性不足的功能呢?其实原理很简单,只有8行代码:classTest:def__init__(self,num):self。num=numdef__or__(self,other):print(f'我右边有东西,是:{other}')x=Test(100)x|55这里涉及一个盲点和两个真正的知识点。盲点是你可能会想|到|是一个字符,但它是3个字符;你可能会看到|拼接|作为一个整体,但它实际上是3个部分:左边是splice,右边是|。如果加上空格,就很明显了:真正的两个知识点是__or__和__ror__这两个魔术方法和偏函数partial。而Change本身只是一个普通类,__or__和__ror__定义了该类实例遇到|时的具体行为。在左边和|在右侧。让我们一一谈谈。第一个是__or__。它定义了实例右侧遇到|时的具体行为。比如我们用一个简单的代码来测试:classTest:def__init__(self,num):self.num=numdef__or__(self,other):print(f'我右边有东西,是:{其他}')x=测试(100)x|55运行效果如下图:但是如果把竖线放在左边,会报错,如下图:而__ror__是用来定义|的in当实例离开时,它的行为:所以,在我们最初的例子中,2|到|10,其实应该理解为:给Change(range)返回的实例2|生成一个中间对象,我们假设它是xx|10生成结果。在我们的演示示例中,2|首先进入Change类的__ror__方法:def__ror__(self,other):self.func=partial(self.func,other)returnself其中,开头的self.func就是我们传递的参数范围在我们初始化实例Change(range)的时候。所以partial(self.func,other)等价于partial(range,2)。关于partial函数partial,可以看我的文章:Partialfunction:AnotherwaytosetdefaultparametersinPython。简单来说,使用部分函数,??你可以将一些参数传递给一个真正的函数,剩下的参数稍后再填充。可能你是日常开发者,实例方法返回self的情况很少见。关于这种写法,可以看我的文章:一日一技:用Python实现链式调用。换句话说,从1|返回的是什么?仍然是Change类的一个实例,我们简称为x。该实例的属性self.func的值为partial(range,2)。接下来,x|10、调用了__or__方法,所以此时执行partial(range,2)(10)。偏函数的参数补齐了,所以里面的range才真正起作用,变成了range(2,10)。到目前为止,我们已经彻底分析了Change类。如您所知,Python中有许多魔术方法。如果你不想使用|,你可以使用其他方法,例如:或:或:同时,你甚至可以直接将这个Change类用作装饰器。任何接受两个参数的函数都可以使用这个装饰器。例子:总结在最后。众所周知,我非常反对在工作代码中炫耀,因为炫耀很难阅读,也很难维护。虽然今天不推荐大家使用这个技巧性的方法,但是仅仅8行代码就包含了非常多的知识点,值得一玩。