不会用partial,别说你会python

作为程序猿,特别是Pythoner,编写可重用的代码是一件好事,对吧?因为这样做的好处就是可以使你的代码和其他人的代码变得更加轻松,但这是有前提的,必须要以非常清晰和可维护的方式来完成。最近小胖一直在玩「functools.partial」函数,发现它可以帮助编写可重用代码。虽然官方文档中有一个很好的演示 functools.partial 的例子,但它太正式了。今天小胖就把自己平时使用的一些有趣的例子分享给大家。

functools.partial

什么functools.partial是:

  • 使用已填写一个或多个参数的函数创建新的版本。
  • 新版本的功能是基于旧版本的。

接下来,我将使用代码来解释这是如何工作的,而不是深入解释他的代码。

简单用法

首先,假设创建一个明确执行幂运算的函数。通过这种方式,我们可以在任何数量上获得 平方,立方和其他次方的操作。其实下面的函数就是模仿了Python的内置pow() 函数

def power(base, exponent):
    return base ** exponent

现在,如果想要具有power()函数的平方和立方函数呢?当然,我们可以这样做:

def square(base):
    return power(base, 2)

def cube(base):
    return power(base, 3)

当然没有问题,但是如果我们想要创建15或20个power()函数变体呢?他们中的1000个呢?不用说,写这么多重复的代码是烦人的。这是partial发挥作用的时候了。我们可以使用partial重写我们的square和cube函数,并使用py.test测试它是否成功 :

from functools import partial

square = partial(power, exponent=2)
cube = partial(power, exponent=3)

def test_partials():
    assert square(2) == 4
    assert cube(2) == 8

大家可以自行尝试。刚才,我们使用了function.partial 函数创建了一个新的函数(某种程度上)。我会用更多的测试来证明partial函数创建的是一个幂函数:

def test_partial_docs():
    assert square.keywords == {"exponent": 2}
    assert square.func == power
    assert cube.keywords == {"exponent": 3}
    assert cube.func == power

使用循环,让我们构建并测试10个自定义power()函数:

def test_power_partials():
    # 准备一个存储新函数的列表
    power_partials = []
    for x in range(1, 11):
        # 创建新的函数
        f = partial(power, exponent=x)
        # 将新的函数加入列表中
        power_partials.append(f)
    # 当然我们也可以使用列表解析式来完成上面的工作
    # [partial(power, exponent=x) for x in range(1, 11)]
    # 测试第一个新函数
    assert power_partials[0](2) == 2
    # 测试第五个新函数
    assert power_partials[4](2) == 32
    # 测试第十个新函数
    assert power_partials[9](2) == 1024

高阶使用

我相信上面的例子大家应该都能看懂吧~接下来,我们来看看在类中如何应用partial:

from six import add_metaclass 

class PowerMeta(type):
    def __init__(cls, name, bases, dct):
        # 在这里,我生成50个新函数
        for x in range(1, 51):
            # 这里使用了python的反射
            setattr(
                # cls就是我们这个类了
                cls,
                # 给新函数取一个名字
                "p{}".format(x),
                # 新函数的具体定义
                partial(power, exponent=x)
            )
        super(PowerMeta, cls).__init__(name, bases, dct)

@add_metaclass(PowerMeta)
class PowerStructure(object):
    pass

接下来,就来测试下我们的PowerStructure类:

def test_power_structure_object():
    p = PowerStructure()
    # p2的10次方
    assert p.p2(10) == 100
    # p5的2次方
    assert p.p5(2) == 32
    # p50的2次方
    assert p.p50(2) == 1125899906842624

看起来不错,对吧?但是,我们可以做的更好!

感谢元类的强大功能,我们不需要实例化PowerStructure类!

def test_power_structure_class():
    # 这里就能感受到元类的强大了吧!
    assert PowerStructure.p2(10) == 100
    assert PowerStructure.p5(2) == 32
    assert PowerStructure.p50(2) == 1125899906842624

今天,小胖提供了一些简单的functools.partials例子。我发现它们对于某些任务非常有用,主要是避免重复造轮子。但同时也要小心使用functools.partials,容易造成代码含义不清晰好啦,如果你觉得今天的内容不错的话,不如点个赞?如果真的帮助到你了,也可以给我点打赏,这会让我GC的~


原文发布于微信公众号 - 猿媛牧场(xpchuiit)

原文发表时间:2018-06-02

本文参与腾讯云自媒体分享计划,欢迎正在阅读的你也加入,一起分享。

发表于

我来说两句

0 条评论
登录 后参与评论

相关文章

来自专栏极客猴

Python 中各种时间类型的转换

我们编码过程中经常需要获取当前时间。当然, 这也离不开对时间类型进行转换运算。本文主要讲解 Python 各种时间类型之间的转换。

732
来自专栏battcn

一起学设计模式 - 访问者模式

访问者模式: 预留通路,回调实现。它的实现主要就是通过预先定义好调用的通路,在被访问的对象上定义 accept方法,在访问者的对象上定义 visit方法;然后在...

511
来自专栏顶级程序员

6 个新奇的编程方式,改变你对编码的认知

源 | Reddit 译 | OSC - 周其 我时不时会发现一种编程语言的不同用法它有时候会改变我对编程的看法啊。这篇文章中,我想分享一下让我惊讶的发...

2654
来自专栏Crossin的编程教室

真值表

逻辑判断是编程中极为常用的知识。之前的课我们已经说过,见第6课和第11课。但鉴于逻辑运算的重要性,今天我再把常用的运算结果总结一下,供大家参考。 这种被称为“真...

2104
来自专栏老秦求学

汇编语言学习01

汇编语言(8086cpu) 恩,学习一门课程,我觉得应该有一定的条理性,而且自己要勤加思考才能学好,条理性:最好就是先整体的介绍一下全本书,然后再详细的介绍各个...

2729
来自专栏编程

Python萌新在九九乘法表中栽过的跟头

对于一个只听过一节python视频课的新手,写出九九乘法表毫无疑问是一件充满挑战的事情,所以写之前我在菜鸟教程中看了一些基础知识,看了点儿之后觉得不是特别难,于...

1898
来自专栏AI科技大本营的专栏

送书 | 跟我一起学《流畅的Python》

本文引自图灵新书《流畅的Python》的第一章——Python数据模型。本书由奋战在Python开发一线近20年的Luciano Ramalho执笔,Victo...

3294
来自专栏码洞

编程的智慧

编程是一种创造性的工作,是一门艺术。精通任何一门艺术,都需要很多的练习和领悟,所以这里提出的“智慧”,并不是号称一天瘦十斤的减肥药,它并不能代替你自己的勤奋。然...

391
来自专栏我是攻城师

理解递归算法的原理

递归(Recursion)在计算机科学中是指一种通过重复将问题分解为同类的子问题而解决问题的方法,其核心思想是分治策略。 递归式方法可以被用于解决很多的计算机科...

771
来自专栏java思维导图

经典面试问题: Top K 之 -- 海量数据找出现次数最多或,不重复的

林冠宏 / 指尖下的幽灵 仅列举一些解决方法,事实的解决方案是非常多的。 这些问题都是面临着有如下的考虑: 内存不足以放下所有的数。 机器CPU的核数不够。 ...

3587

扫码关注云+社区