python中编函数_在python中编写函数

Aaron Hall..

10

递归实现

这是一个相当优雅的递归实现,为了清晰起见,它使用了Python 3的功能:

def strict_compose(*funcs):

*funcs, penultimate, last = funcs

if funcs:

penultimate = strict_compose(*funcs, penultimate)

return lambda *args, **kwargs: penultimate(last(*args, **kwargs))

Python 2兼容版本:

def strict_compose2(*funcs):

if len(funcs) > 2:

penultimate = strict_compose2(*funcs[:-1])

else:

penultimate = funcs[-2]

return lambda *args, **kwargs: penultimate(funcs[-1](*args, **kwargs))

这是一个使用延迟评估递归的早期版本:

def lazy_recursive_compose(*funcs):

def inner(*args, _funcs=funcs, **kwargs):

if len(_funcs) > 1:

return inner(_funcs[-1](*args, **kwargs), _funcs=_funcs[:-1])

else:

return _funcs[0](*args, **kwargs)

return inner

两者似乎都会在每次递归调用时创建一个新的元组和参数的dict.

所有建议的比较:

让我们测试一些这些实现并确定哪个是最高性能的,首先是一些单个参数函数(谢谢你戳):

def square(x):

return x ** 2

def increment(x):

return x + 1

def half(x):

return x / 2

这是我们的实现,我怀疑我的迭代版本是第二高效的(手动编写自然会最快),但这可能部分是由于它避免了在函数之间传递任意数量的参数或关键字参数的困难 - 在大多数情况下我们只会看到传递的琐碎的一个论点.

from functools import reduce

def strict_recursive_compose(*funcs):

*funcs, penultimate, last = funcs

if funcs:

penultimate = strict_recursive_compose(*funcs, penultimate)

return lambda *args, **kwargs: penultimate(last(*args, **kwargs))

def strict_recursive_compose2(*funcs):

if len(funcs) > 2:

penultimate = strict_recursive_compose2(*funcs[:-1])

else:

penultimate = funcs[-2]

return lambda *args, **kwargs: penultimate(funcs[-1](*args, **kwargs))

def lazy_recursive_compose(*funcs):

def inner(*args, _funcs=funcs, **kwargs):

if len(_funcs) > 1:

return inner(_funcs[-1](*args, **kwargs), _funcs=_funcs[:-1])

else:

return _funcs[0](*args, **kwargs)

return inner

def iterative_compose(*functions):

"""my implementation, only accepts one argument."""

def inner(arg):

for f in reversed(functions):

arg = f(arg)

return arg

return inner

def _compose2(f, g):

return lambda *a, **kw: f(g(*a, **kw))

def reduce_compose1(*fs):

return reduce(_compose2, fs)

def reduce_compose2(*funcs):

"""bug fixed - added reversed()"""

return lambda x: reduce(lambda acc, f: f(acc), reversed(funcs), x)

并测试这些:

import timeit

def manual_compose(n):

return square(increment(half(n)))

composes = (strict_recursive_compose, strict_recursive_compose2,

lazy_recursive_compose, iterative_compose,

reduce_compose1, reduce_compose2)

print('manual compose', min(timeit.repeat(lambda: manual_compose(5))), manual_compose(5))

for compose in composes:

fn = compose(square, increment, half)

result = min(timeit.repeat(lambda: fn(5)))

print(compose.__name__, result, fn(5))

结果

我们得到以下输出(Python 2和3中的相同幅度和比例):

manual compose 0.4963762479601428 12.25

strict_recursive_compose 0.6564744340721518 12.25

strict_recursive_compose2 0.7216697579715401 12.25

lazy_recursive_compose 1.260614730999805 12.25

iterative_compose 0.614982972969301 12.25

reduce_compose1 0.6768529079854488 12.25

reduce_compose2 0.9890829260693863 12.25

我的期望得到了证实:当然,最快的是手动功能组合,然后是迭代实现.惰性递归版本要慢得多 - 可能是因为每个函数调用都会创建一个新的堆栈帧,并为每个函数创建一个新的函数元组.

为了更好也许更现实的比较,如果您删除**kwargs和更改*args到arg的功能,即用他们的将是更好的性能,我们可以更好地比较苹果苹果-从手工组成这里,一旁,reduce_compose1胜其次strict_recursive_compose:

manual compose 0.443808660027571 12.25

strict_recursive_compose 0.5409777010791004 12.25

strict_recursive_compose2 0.5698030130006373 12.25

lazy_recursive_compose 1.0381018499610946 12.25

iterative_compose 0.619289995986037 12.25

reduce_compose1 0.49532539502251893 12.25

reduce_compose2 0.9633988010464236 12.25

只有一个arg的函数:

def strict_recursive_compose(*funcs):

*funcs, penultimate, last = funcs

if funcs:

penultimate = strict_recursive_compose(*funcs, penultimate)

return lambda arg: penultimate(last(arg))

def strict_recursive_compose2(*funcs):

if len(funcs) > 2:

penultimate = strict_recursive_compose2(*funcs[:-1])

else:

penultimate = funcs[-2]

return lambda arg: penultimate(funcs[-1](arg))

def lazy_recursive_compose(*funcs):

def inner(arg, _funcs=funcs):

if len(_funcs) > 1:

return inner(_funcs[-1](arg), _funcs=_funcs[:-1])

else:

return _funcs[0](arg)

return inner

def iterative_compose(*functions):

"""my implementation, only accepts one argument."""

def inner(arg):

for f in reversed(functions):

arg = f(arg)

return arg

return inner

def _compose2(f, g):

return lambda arg: f(g(arg))

def reduce_compose1(*fs):

return reduce(_compose2, fs)

def reduce_compose2(*funcs):

"""bug fixed - added reversed()"""

return lambda x: reduce(lambda acc, f: f(acc), reversed(funcs), x)

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值