序
作为程序猿,特别是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的~