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? У меня есть крошечная библиотека, которая делает трубопроводы, может вас заинтересовать
Для справки вот полная грамматика:
Я тоже искал способ сделать это. Поэтому я создал библиотеку Python под названием Pypework.
Вы просто добавляете префикс, такой как f.
в начале каждого вызова функции, чтобы сделать его конвейерным. Затем вы можете связать их вместе, используя >>
оператор, вот так:
"Lorem Ipsum" >> f.lowercase >> f.replace(" ", "_") # -> "lorem_ipsum"
Или через несколько строк, если они заключены в скобки, например:
(
"Lorem Ipsum"
>> f.lowercase
>> f.replace(" ", "_")
)
# -> "lorem_ipsum"