Clojure стиль функции «многопоточность» в Python - PullRequest
19 голосов
/ 10 февраля 2011

Clojure имеет макрос "->", который рекурсивно вставляет каждое выражение в качестве первого аргумента следующего выражения.

Это значит, что я мог написать:

(-> arg f1 f2 f3)

и он ведет себя как (оболочка труб):

f3(f2(f1(arg)))

Я хотел бы сделать это на Python; однако, поиск кажется кошмаром! Я не смог найти "->", и я не смог найти функцию Python threading !

Есть ли способ перегрузить, скажем, | оператор, чтобы я мог написать это на Python?

arg | f1 | f2 | f3

Спасибо!

Ответы [ 8 ]

21 голосов
/ 10 февраля 2011

Или, возможно, используйте функцию уменьшения следующим образом:

reduce(lambda x,f : f(x), [f1,f2,f3], arg)
15 голосов
/ 10 февраля 2011

Вы можете легко реализовать что-то подобное самостоятельно.

def compose(current_value, *args):
    for func in args:
        current_value = func(current_value)
    return current_value

def double(n):
    return 2*n

print compose(5, double, double) # prints 20
9 голосов
/ 30 марта 2011

Или попробуйте https://mdk.fr/blog/pipe-infix-syntax-for-python.html Модуль, обеспечивающий синтаксис, такой как:

  fib() | take_while(lambda x: x < 1000000)
        | where(lambda x: x % 2)
        | select(lambda x: x * x)
        | sum()
8 голосов
/ 10 февраля 2011

Опираясь на решение Говарда:

def T(*args):
  return reduce(lambda l, r: r(l), args)

def dbl(n):
    return 2*n

T(5,dbl,dbl)
#=> 20

T(5,dbl,dbl,lambda x: 3*x)
#=> 60
3 голосов
/ 10 февраля 2011

Хотя я сочувствую желанию создавать классные новые языковые конструкции (например, макросы Lisp), это не совсем философия Python, чтобы сделать это:

>>> import this
[...]
There should be one-- and preferably only one --obvious way to do it.

Но, как сказали респонденты, выможет сделать вашу функцию цепочкой различными способами.Вот тот, который, возможно, более явно похож на Лисп, если он подходит вам:

a = lambda x: x*2
b = lambda x: x+1

def chain(first, *args):
    if len(args) == 0:
        return first
    else:
        return first(chain(*args))

print chain(b, a, 1)
2 голосов
/ 12 июля 2016

Немного опоздал на вечеринку, но вот более чистый метод, Имо. Подойдет большинству потребностей FP.

def stream(*args):
    return reduce(lambda a, t: t[0](t[1], a), args[1:], args[0])

Базовая карта, фильтр, уменьшить:

>>> my_list = [1, 2, 3, 4, 5]
>>> stream(my_list, 
...    (map,    lambda x: x ** 2),
...    (filter, lambda x: x < 20),
...    (reduce, lambda a, x: a + x))
30
1 голос
/ 25 марта 2015

В библиотеке pytoolz есть функция потока (на самом деле их две; они немного отличаются друг от друга в функциях с несколькими аргументами).

Существует также реализация Python библиотеки Pythonназывается cytoolz , что, вероятно, более эффективно.Может быть установлен с помощью pip.

0 голосов
/ 10 февраля 2011

Нет, нет (по крайней мере, здраво).И не хотел бы.Почему бы просто не написать f3(f2(f1(arg)))?Или, что еще лучше, смоделируйте вашу проблему так, чтобы она не требовала рекурсии.

Вы можете перегружать |, заключая выражения в класс и определяя __or__ в этом классе, но, пожалуйста,ради любви Гвидо, не делай этого.

Ты мог бы также сделать то, что написал btilly, но я бы тоже не советовал.Работайте в пределах того, что вам дает язык.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...