Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/python/331.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
在Python中部分应用的性能方法?_Python_Lambda_Partial Application - Fatal编程技术网

在Python中部分应用的性能方法?

在Python中部分应用的性能方法?,python,lambda,partial-application,Python,Lambda,Partial Application,我正在寻找一种在python中部分应用函数的方法,这种方法简单易懂、可读、可恢复,并且尽可能少的代码错误。最重要的是,我希望样式尽可能具有性能—堆栈上的帧越少越好,部分应用函数的内存占用也越少越好。我考虑了以下4种风格和示例: 导入工具 def倍增器(m): def内部(x): 返回m*x 返回内部 def分配(n,d): 退货不适用 def分配器(d): 返回functools.partial(除法,d=d) 时间2=乘数(2) 打印(时间2(3))#6 by2=分隔器(2) 打印(by2(6

我正在寻找一种在python中部分应用函数的方法,这种方法简单易懂、可读、可恢复,并且尽可能少的代码错误。最重要的是,我希望样式尽可能具有性能—堆栈上的帧越少越好,部分应用函数的内存占用也越少越好。我考虑了以下4种风格和示例:

导入工具
def倍增器(m):
def内部(x):
返回m*x
返回内部
def分配(n,d):
退货不适用
def分配器(d):
返回functools.partial(除法,d=d)
时间2=乘数(2)
打印(时间2(3))#6
by2=分隔器(2)
打印(by2(6))#3.0
by3=functools.partial(除法,d=3)
打印(by3(9))#3.0
by4=λn:除以(n,4)
打印(by4(12))#3.0
我对它们的分析如下:

times2
是一个嵌套的东西。我想python用
m
绑定了一个闭包,一切都很好。代码是可读的(我认为)和简单易懂的。没有外部库。这是我今天用的款式

by2
有一个显式命名函数,使用户可以轻松使用。它使用functools,因此可以提供额外的导入。我在某种程度上喜欢这种风格,因为它是透明的,如果我愿意,我可以选择以其他方式使用
divide
。与无法访问的
内部
进行对比

by3
类似于
by2
,但会迫使代码的读者对
功能工具感到舒适。部分
,因为他们的功能就在眼前。我不太喜欢的是PyCharm不能给我的工具提示
functools.partial的参数应该是什么,因为它们实际上是
by3
的参数。每次定义新的部分应用程序时,我都必须知道自己的签名

by4
打字很简单,因为我可以自动完成。它不需要导入
functools
。不过我觉得它看起来不像蟒蛇。此外,我总是对使用python中的lambdas工作来确定变量/闭包的范围感到不舒服。永远不知道那是怎么回事


这些样式之间的逻辑区别是什么?它们是如何影响内存和CPU的?第一种方法似乎是最有效的。我调整了您的代码,使所有4个函数计算的数学函数完全相同:

import functools,timeit

def multiplier(m):
    def inner(x):
        return m * x

    return inner

def mult(x,m):
    return m*x

def multer(m):
    return functools.partial(mult,m=m)

f1 = multiplier(2)
f2 = multer(2)
f3 = functools.partial(mult,m=2)
f4 = lambda x: mult(x,2)

print(timeit.timeit('f1(10)',setup = 'from __main__ import f1'))
print(timeit.timeit('f2(10)',setup = 'from __main__ import f2'))
print(timeit.timeit('f3(10)',setup = 'from __main__ import f3'))
print(timeit.timeit('f4(10)',setup = 'from __main__ import f4'))
典型输出(在我的机器上):


两种
functools.partial
方法是相同的(因为其中一种方法只是另一种方法的包装器),第一种方法的速度是另一种方法的两倍,最后一种方法介于两者之间(但更接近第一种方法)。在一个简单的闭包上使用
functools
会有明显的开销。因为闭包方法也可以说更具可读性(并且比lambda更灵活,lambda不能很好地扩展到更复杂的函数)我会同意的。

从技术上讲,您缺少了另一个选项,就像您希望做的一样,您可以使用
functools.partial
获得默认的第一个参数,而无需重新设计轮子

它不仅是最快的选项,而且与自定义函数或lambda语句相比,它使用的空间最少。这是一个
部分
的事实,这就是为什么它使用与其他部分相同的空间,我认为这是最好的路径

from timeit import timeit
from functools import partial
from sys import getsizeof
from operator import mul

def multiplier(m):
    def inner(x):
        return m * x
    return inner

def mult(x,m):
    return m*x

def multer(m):
    return partial(mult,m=m)

f1 = multiplier(2)
f2 = multer(2)
f3 = partial(mult,m=2)
f4 = lambda n: mult(n,2)
f5 = partial(mul, 2)
from_main = 'from __main__ import {}'.format

print(timeit('f1(10)', from_main('f1')), getsizeof(f1))
print(timeit('f2(10)', from_main('f2')), getsizeof(f2))
print(timeit('f3(10)', from_main('f3')), getsizeof(f3))
print(timeit('f4(10)', from_main('f4')), getsizeof(f4))
print(timeit('f5(10)', from_main('f5')), getsizeof(f5))
输出

0.5278953390006791 144
1.0804575479996856 96
1.0762036349988193 96
0.9348237040030654 144
0.3904160970050725 96

这应该可以回答您关于内存使用和速度的问题。

这是一个相当广泛的问题。我不认为在这方面有任何共识,所以使用感觉正确的方法。就功能而言,它们基本上是等价的。就速度而言,你可以用
timeit
自己检查一下(不要认为会有很大的区别)@JohnColeman我明白这一点。我将重写以缩小范围!如果您具有完全相同的函数(例如,发送x到2x的函数),则比较可能更有直接意义用四种不同的方式定义,而不是用四种不同的方式定义四种不同的函数。可能也很有趣:@JohnColeman感谢你指出在任何情况下做同样的数学对于使其具有可比性的重要性。当我开始重写这个问题时,我意识到你下面的答案实际上很好地回答了我的问题。此外,它还为我提供了我自己在机器上解决问题所需的工具,并提供了上下文功能。非常感谢。我不太明白你的答案。您的意思是可以使用
操作符.mul
,这有点离题,因为乘法函数可能只是一个简单的测试示例,而不是OP真正要使用的。然后你说对于
operator.mul
partial
是最好的,因此
partial
是最好的(在所有情况下?),即使它比
def
函数慢?我在所有情况下都说了什么?在这种情况下,使用
partial
operator.mul
是最快的,因为OP似乎要做的是向另一个添加默认参数,但不是最重要的,因为partial不能接受位置参数。这是一个可以考虑的选择。我只是说,
operator.mul
是另一种选择,比自己制作更快。
0.5278953390006791 144
1.0804575479996856 96
1.0762036349988193 96
0.9348237040030654 144
0.3904160970050725 96