python可调用对象_Python避免使用lambda作为需要两个可调用对象的键(函数组合)...

bd96500e110b49cbb3cd949968f18be7.png

I was working on project euler problem 14 and as a first attempt I whipped up this brute-force solution:

def collatz(n, memo={1: [1]}):

if n not in memo:

memo[n] = [n] + collatz(3 * n + 1 if n % 2 else n // 2)

return memo[n]

def p014():

return max(xrange(1, 10**6), key=lambda n: len(collatz(n)))

My question is about that lambda, I'm usually reluctant to use them but I don't know any elegant way to avoid it in this case. Is there something in functools or other to chain two callables, or any other neat alternative I'm missing?

解决方案

It would be lovely if there were a compose function -- perhaps in functools. There is not, nor do I expect there will be, alas. In the words of Raymond Hettinger,

It has been previously discussed and rejected in other forums. One of the issues is that the usual mathematical order is unintuitive and not self-documenting -- i.e. is compose(f,g) the same as f(g(x)) or g(f(x))? Also, it is already dirt simple to create your own compose function or to do the composition directly: h = lambda x: f(g(x)).

Here are two simple implementations of compose as a callable class that you may find useful though:

# Scott Daniels, http://code.activestate.com/recipes/52902-function-composition/

# Lightly edited for style.

class Compose(object):

'''Compose functions. compose(f,g,x...)(y...) = f(g(y...),x...))'''

def __init__(self, f, g, *args, **kwargs):

self.f = f

self.g = g

self.pending = args[:]

self.kwargs = kwargs.copy()

def __call__(self, *args, **kwargs):

return self.f(self.g(*args, **kwargs), *self.pending, **self.kwargs)

class Starcompose:

'''Compose functions. Starcompose(f,g,x...)(y...) = f(*g(y...),x...))'''

TupleType = type(())

def __init__(self, f, g, *args, **kwargs):

self.f = f

self.g = g

self.pending = args[:]

self.kwargs = kwargs.copy()

def __call__(self, *args, **kwargs):

mid = self.g(*args, **kwargs)

if isinstance(mid, self.TupleType):

return self.f(*(mid + self.pending), **self.kwargs)

return self.f(mid, *self.pending, **self.kwargs)

Also, see the functional package, which inspired this very simple compose_many function of mine a while ago:

def compose(f1, f2):

def composition(*args, **kwargs):

return f1(f2(*args, **kwargs))

return composition

def compose_many(*funcs):

return reduce(compose, funcs)

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值