functools (partial)让Python调用多参数函数更优雅

简单例子

from functools import partial

def Add(a,b,c,d,e):
    return a + b + c + d + e

add_e = partial(Add,1,2,3,4) # 可固定a,b,c,d参数,简化函数使用
result = add_e(6)
print(result)

复杂的例子

from functools import partial

def Add(a,b,c,d,e):
    return a + b + c + d + e

add_e = partial(Add,1,2,3,4) # 可固定a,b,c,d参数,简化函数使用
result = add_e(6)
print(result)

典型应用

典型的,在函数执行时,要带上所有必要的参数进行调用,然后,有时参数可以在函数调用之前提前获知,这种情况下,一个函数有一个或多个参数预先就能用上,以遍函数能够有更少的参数进行调用.

import functools
 
def add(a, b):
    return a + b
add(4, 2)
6
 
plus3 = functools.partial(add, 3)
plus5 = functools.partial(add, 5)
plus3(4)
7
plus3(7)
10
plus5(10)
15

问题引入

你有一个被其他python代码使用的collable对象,可能是一个回调函数或者一个处理器,但是其参数太多啦,导致调用时出错.

解决方案

如果需要减少某个函数的参数个数,可以使用functional.parial(), 该函数允许你给一个或多个参数设置固定的值,减少接下来被调用时的参数个数,为了演示清楚,假设你有下面这样的函数:

def spam(a, b, c, d):
    print(a, b, c, d)

现在我们使用 p a r t i a l ( ) partial() partial()函数来固定某些参数的值.

>>> from functools import partial
>>> s1 = partial(spam, 1) # a = 1
>>> s1(2, 3, 4)
1 2 3 4
>>> s1(4, 5, 6)
1 4 5 6
>>> s2 = partial(spam, d=42) # d = 42
>>> s2(1, 2, 3)
1 2 3 42
>>> s2(4, 5, 5)
4 5 5 42
>>> s3 = partial(spam, 1, 2, d=42) # a = 1, b = 2, d = 42
>>> s3(3)
1 2 3 42
>>> s3(4)
1 2 4 42
>>> s3(5)
1 2 5 42

,可以看出parial()某些固定参数并返回一个新的collable对象,这个新的collable对象接收未赋值的参数,然后跟之前已经赋值的参数合并起来,最后将所有参数传递给原始函数.

举例计算两点间的距离排序

本节课要解决的问题是让原本不兼容的代码可以一起工作,下面我会举出一系列的例子.
第一个例子是,假设你有一个点的列表来表示(x,y)坐标元组。 你可以使用下面的函数来计算两点之间的距离:

points = [ (1, 2), (3, 4), (5, 6), (7, 8) ]
import math
def distance(p1, p2):
    x1, y1 = p1
    x2, y2 = p2
    return math.hypot(x2 - x1, y2 - y1)

说明一下这里的math.hypot默认是以坐标原点为几点计算坐标到原点的直线距离:

import math
print(math.hypot(6,8))
>>>10

现在假设,你想以某个点为基点,根据点和基点之间的距离来排序所有的这些点**,表的 sort() 方法接受一个关键字参数来自定义排序逻辑**, 但是它只能接受一个单个参数的函数(distance()很明显是不符合条件的)。 现在我们可以通过使用 partial() 来解决这个问题:

>>> pt = (4, 3)
>>> points.sort(key=partial(distance,pt))
>>> points
[(3, 4), (1, 2), (5, 6), (7, 8)]
>>>

微调回调函数

更进一步,parial()通常被用来微调其他库函数**,所使用的回调函数参数,**例如,下面是一段代码, 使用 multiprocessing 来异步计算一个结果值, 然后这个值被传递给一个接受一个result值和一个可选logging参数的回调函数

def output_result(result, log=None):
    if log is not None:
        log.debug('Got: %r', result)
 
# A sample function
def add(x, y):
    return x + y
 
if __name__ == '__main__':
    import logging
    from multiprocessing import Pool
    from functools import partial
 
    logging.basicConfig(level=logging.DEBUG)
    log = logging.getLogger('test')
 
    p = Pool()
    p.apply_async(add, (3, 4), callback=partial(output_result, log=log))
    p.close()
    p.join()

当给apply_async()提供回调函数时,通过使用partial()传递额外的logging参数,而multiprocessing 对这些一无所知_其仅仅使用单个值来调用回调函数.
作为一个类似的例子,,考虑下编写网络服务器的问题,socketserver 模块让它变得很容易。 下面是个简单的echo服务器:

from socketserver import StreamRequestHandler, TCPServer
 
class EchoHandler(StreamRequestHandler):
    def handle(self):
        for line in self.rfile:
            self.wfile.write(b'GOT:' + line)
 
serv = TCPServer(('', 15000), EchoHandler)
serv.serve_forever()

总结

慢慢根据各种函数, p a r i a l ( ) parial() parial()来学习其定义,学习其用法,慢慢的会自己总结出来都行啦.

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

big_matster

您的鼓励,是给予我最大的动力!

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值