Есть ли что-то вроде макроса потока из Clojure в Python? - PullRequest
0 голосов
/ 04 мая 2018

В Clojure я могу сделать что-то вроде этого:

(-> path
      clojure.java.io/resource
      slurp
      read-string)

вместо этого:

(read-string (slurp (clojure.java.io/resource path)))

Это называется threading в терминологии Clojure и помогает избавиться от множества скобок.

В Python, если я пытаюсь использовать функциональные конструкции, такие как map, any или filter, мне приходится вкладывать их друг в друга. Есть ли в Python конструкция, с помощью которой я могу сделать нечто похожее на многопоточность (или конвейерную обработку) в Clojure?

Я не ищу полнофункциональную версию, так как в Python нет макросов, я просто хочу покончить с множеством скобок, когда я занимаюсь функциональным программированием на Python.

Редактировать: В итоге я использовал toolz , который поддерживает pipe ing.

Ответы [ 2 ]

0 голосов
/ 06 мая 2018

Я хотел довести это до крайности и делать все динамически.

В сущности, приведенный ниже класс Chain позволяет объединять функции вместе, подобно макросам Clojure -> и ->>. Он поддерживает оба потока в первый и последний аргументы.

Функции разрешаются в следующем порядке:

  1. Метод объекта
  2. Локальная переменная
  3. Встроенная переменная

код:

class Chain(object):
    def __init__(self, value, index=0):
        self.value = value
        self.index = index
    def __getattr__(self, item):
        append_arg = True
        try:
            prop = getattr(self.value, item)
            append_arg = False
        except AttributeError:
            try:
                prop = locals()[item]
            except KeyError:
                prop = getattr(__builtins__, item)
        if callable(prop):
            def fn(*args, **kwargs):
                orig = list(args)
                if append_arg:
                    if self.index == -1:
                        orig.append(self.value)
                    else:
                        orig.insert(self.index, self.value)
                return Chain(prop(*orig, **kwargs), index=self.index)
            return fn
        else:
            return Chain(prop, index=self.index)

Обрабатывать каждый результат как первый аргумент

file = Chain(__file__).open('r').readlines().value

Обрабатывать каждый результат как последний аргумент

result = Chain(range(0, 100), index=-1).map(lambda x: x * x).reduce(lambda x, y: x + y).value
0 голосов
/ 04 мая 2018

Вот простая реализация идеи @ deceze (хотя, как указывает @Carcigenicate, в лучшем случае это частичное решение):

import functools
def apply(x,f): return f(x)
def thread(*args):
    return functools.reduce(apply,args)

Например:

def f(x): return 2*x+1
def g(x): return x**2
thread(5,f,g) #evaluates to 121
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...