Лучшая функция в Python
Я работаю на Python. Недавно я обнаружил замечательный маленький пакет под названием fn. Я использовал его для создания функции.
Например, вместо:
baz(bar(foo(x))))
с fn, вы можете написать:
(F() >> foo >> bar >> baz)(x) .
Когда я увидел это, я сразу подумал о Clojure:
(-> x foo bar baz) .
Но обратите внимание, как в Clojure вход находится слева. Интересно, возможно ли это в python/fn.
Ответы
Ответ 1
Вы не можете реплицировать точный синтаксис, но вы можете сделать что-то подобное:
def f(*args):
result = args[0]
for func in args[1:]:
result = func(result)
return result
Кажется, работает:
>>> f('a test', reversed, sorted, ''.join)
' aestt'
Ответ 2
Вы не можете получить точный синтаксис, хотя вы можете получить что-то вроде F(x)(foo, bar, baz)
. Вот простой пример:
class F(object):
def __init__(self, arg):
self.arg = arg
def __call__(self, *funcs):
arg = self.arg
for f in funcs:
arg = f(arg)
return arg
def a(x):
return x+2
def b(x):
return x**2
def c(x):
return 3*x
>>> F(2)(a, b, c)
48
>>> F(2)(c, b, a)
38
Это немного отличается от ответа Blender, поскольку он хранит аргумент, который впоследствии может быть повторно использован с различными функциями.
Это похоже на противоположное нормальному приложению: вместо указания функции перед фронтом и оставления некоторых аргументов, которые будут указаны позже, вы указываете аргумент и оставляете функцию (функции) указанной позже. Это интересная игрушка, но трудно подумать, почему вы действительно этого хотите.
Ответ 3
Если вы хотите использовать fn
, с небольшим взломом вы можете немного приблизиться к синтаксису Clojure:
>>> def r(x): return lambda: x
>>> (F() >> r(x) >> foo >> bar >> baz)()
Посмотрите, как я добавил еще одну функцию в начале цепочки композиций, которая будет возвращать x
при вызове. Проблема заключается в том, что вам все равно придется называть вашу скомпонованную функцию просто без каких-либо аргументов.
Я думаю, что ответ @Blender - ваш лучший выбор, пытающийся эмулировать функцию потока Clojure в Python.
Ответ 4
Я придумал этот
def _composition(arg, *funcs_and_args):
"""
_composition(
[1,2,3],
(filter, lambda x: x % 2 == 1),
(map, lambda x: x+3)
)
#=> [4, 6]
"""
for func_and_args in funcs_and_args:
func, *b = func_and_args
arg = func(*b, arg)
return(arg)
Ответ 5
Это, похоже, работает для простого ввода. Не уверен, что это стоит усилий для сложного ввода, например, ((42, 'spam'), {'spam': 42})
.
def compose(function, *functions):
return function if not functions else \
lambda *args, **kwargs: function(compose(*functions)(*args, **kwargs))
def rcompose(*functions):
return compose(*reversed(functions))
def postfix(arg, *functions):
return rcompose(*functions)(arg)
Пример:
>>> postfix(1, str, len, hex)
'0x1'
>>> postfix(1, hex, len)
3