Python Infix вперед трубы

Я пытаюсь реализовать функциональность прямой трубы, как в Bash | или R недавно %>%, Я видел эту реализацию http://dev-tricks.net/pipe-infix-syntax-for-python, но для этого необходимо заранее определить все функции, которые могут работать с конвейером. Собираясь к чему-то совершенно общему, вот о чем я думал до сих пор.

Эта функция применяет свой первый аргумент ко второму (функция)

def function_application(a,b):
    return b(a)

Так, например, если у нас есть функция возведения в квадрат

def sq(s):
    return s**2

мы могли бы вызвать эту функцию таким громоздким способом function_application(5,sq), Чтобы сделать шаг ближе к передней трубе, мы хотим использовать function_application с инфиксной записью.

Исходя из этого, мы можем определить Infix класс, чтобы мы могли обернуть функции в специальные символы, такие как |,

class Infix:
    def __init__(self, function):
        self.function = function
    def __ror__(self, other):
        return Infix(lambda x, self=self, other=other: self.function(other, x))
    def __or__(self, other):
        return self.function(other)

Теперь мы можем определить наш канал, который является просто инфиксной версией функции function_application,

p = Infix(function_application)

Так что мы можем делать такие вещи

5 |p| sq
25

или же

[1,2,3,8] |p| sum |p| sq
196

После этого многословного объяснения у меня возникает вопрос, есть ли способ переопределить ограничения на допустимые имена функций. Здесь я назвал трубу p, но возможно ли перегрузить не алфавитно-цифровой символ? Могу ли я назвать функцию > так что моя труба |>|?

2 ответа

Решение

Быстрый ответ:

Вы не можете реально использовать |>| в Python, как минимум, вам нужно | * > * | где * должен быть идентификатор, число, строка или другое выражение.

Длинный ответ:

Каждая строка - это утверждение ( простое или составное), stmt может быть несколько вещей, среди которых выражение, выражение является единственной конструкцией, которая позволяет использовать оператор или | и больше, чем сравнение > (или все операторы и сравнения по этому вопросу < > <= >= | ^ & >> << - + % / //), каждому выражению нужна левая сторона и правая сторона, в конечном итоге находящаяся в форме lhs op rhsи левая, и правая часть могут быть другим выражением, но выходной регистр - использование первичного (за исключением ненарного -, ~ а также + что нужно просто rhs), основной будет сводиться к идентификатору, номеру или строке, поэтому в конце дня вы должны иметь идентификатор [a-zA-Z_][a-zA-Z_0-9]* вдоль стороны |,

Рассматривали ли вы другой подход, например, один класс, который переопределяет оператор or вместо класса infix? У меня есть крошечная библиотека, которая делает трубопроводы, может вас заинтересовать

Для справки вот полная грамматика:

https://docs.python.org/2/reference/grammar.html

Я тоже искал способ сделать это. Поэтому я создал библиотеку Python под названием Pypework.

Вы просто добавляете префикс, такой как f. в начале каждого вызова функции, чтобы сделать его конвейерным. Затем вы можете связать их вместе, используя >> оператор, вот так:

"Lorem Ipsum" >> f.lowercase >> f.replace(" ", "_") # -> "lorem_ipsum"

Или через несколько строк, если они заключены в скобки, например:

(
  "Lorem Ipsum"
    >> f.lowercase
    >> f.replace(" ", "_")
)

# -> "lorem_ipsum"
Другие вопросы по тегам