Python функциональное программирование - PullRequest
0 голосов
/ 04 января 2012

Есть моя проблема:

Предположим, у нас есть 3 функции: f, g, h и следующий код

y = f(x)
a = g(y)
b = h(y)

Я хочу сделать это в одной строке, например:

a,b = g(f(x)),h(f(x))

но это неэффективно, если f очень медленный (и не кеширует свой результат)

У меня есть одно решение с генератором:

a,b = ((g(y),h(y)) for y in (f(x),)).next()

но это не очень читабельно

Я бы хотел сделать что-то подобное:

with  f(x) as y: a,b = g(y),h(y)

У кого-нибудь есть идея?

(это чит

y = f(x);a = g(y);b = h(y)

)

код

import time
def f(t): 
    time.sleep(1)
    print 'f called'
    return t

def g(t): return 1

def h(t): return 2

a,b = g(f(x)),h(f(x))
a,b = ((g(y),h(y)) for y in (f(x),)).next()

Ответы [ 3 ]

6 голосов
/ 04 января 2012

Используйте лямбду. Ta-д:

>>> def f(a):
...     return a+1
... 
>>> def g(a):
...     return a*2
... 
>>> def h(a):
...     return a*3
... 
>>> (lambda x: (g(x),h(x)))(1)
(2, 3)
>>> (lambda x: (g(x),h(x)))(f(1))
(4, 6)
>>> a,b=(lambda x: (g(x),h(x)))(f(1))
>>> a
4
>>> b
6
3 голосов
/ 04 января 2012

Я, наверное, здесь не вижу смысла, но не вижу ничего плохого в

y = f(x); a,b = (g(y), h(y))

Если вы выполняете эту операцию достаточно часто в своем коде, и вам нужна простота, то, возможно, вы можете создать служебную функцию, которая отображает аргумент в список функций:

def xmap(v, f_iter):
    "Subjects v to every function in f_iter and returns a list of results"
    return [f(v) for f in f_iter]

Вы можете сделать:

a, b = xmap(f(x), [g, h])  

Идиома map хорошо известна, поэтому этот подход, вероятно, читабелен и вполне понятен, т.е. xmap() похож на map(), но с транспонированными аргументами и функциями .

1 голос
/ 04 января 2012

Если вы хотите использовать оператор with, вы можете просто украсить f() с помощью contextlib.contextmanager и получить из него:

from contextlib import contextmanager

@contextmanager
def f(t):
    time.sleep(1)
    print 'f called'
    yield t

with f(1) as y:
    a, b = g(y), h(y)
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...