Python: jQuery-подобная цепочка функций? - PullRequest
8 голосов
/ 03 декабря 2010

Я не смог найти что-либо на эту тему в Google, поэтому я думаю, что я должен спросить это здесь:

Можно ли связывать функции с помощью Python, как это делает jQuery?

['my', 'list'].foo1(arg1, arg2).foo2(arg1, arg2).foo3(arg1, arg2) #etc...

Я теряю много места и читаемость, когда пишу этот код:

foo3(foo2(foo1(['my', 'list'], arg1, arg2), arg1, arg2), arg1, arg2) #etc...

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

Спасибо!

Ответы [ 5 ]

10 голосов
/ 03 декабря 2010

Пока функция возвращает значение, вы можете связать его. В jQuery метод селектора обычно возвращает сам селектор, что позволяет вам создавать цепочки. Если вы хотите реализовать цепочку в Python, вы можете сделать что-то вроде этого:

class RoboPuppy:

  def bark(self):
    print "Yip!"
    return self

  def growl(self):
    print "Grr!"
    return self

pup = RoboPuppy()
pup.bark().growl().bark()  # Yip! Grr! Yip!

Однако, похоже, ваша проблема в том, что аргументы вашей функции слишком тесны. Цепочка не является решением этой проблемы. Если вы хотите сжать аргументы своей функции, просто присвойте аргументы переменным, прежде чем передавать их в функцию, например:

spam = foo(arg1, arg2)
eggs = bar(spam, arg1, arg2)
ham = foobar(eggs, args)
9 голосов
/ 03 декабря 2010

Вот расширение предложения Саймона ListMutator:

class ListMutator(object):

    def __init__(self, seq):
        self.data = seq

    def foo1(self, arg1, arg2):
        self.data = [x + arg1 for x in self.data]
        # This allows chaining:
        return self

    def foo2(self, arg1, arg2):
        self.data = [x*arg1 for x in self.data]
        return self

if __name__ == "__main__":
    lm = ListMutator([1,2,3,4])
    lm.foo1(2, 0).foo2(10, 0)
    print lm.data

    # Or, if you really must:
    print ListMutator([1,2,3,4]).foo1(2, 0).foo2(10, 0).data

Вы могли бы пойти лучше и заставить ListMutator вести себя как список, используя абстрактные базовые классы коллекций . На самом деле, вы можете создать подкласс list сам, хотя это может ограничить вас от выполнения определенных действий, которые вам могут понадобиться ... и я не знаю, каково общее мнение о подклассах встроенных типов, таких как list.

3 голосов
/ 03 декабря 2010

Если мы говорим о объектных методах, то это тривиально, просто return self из каждого метода. С другой стороны, если вы хотите связать несвязанные функции, для меня не имеет смысла связывать их так, как вы хотите. Конечно, это выглядит красиво, но семантически бессвязно, потому что "." обозначает доступ к атрибуту объекта, а не «цепочку».

1 голос
/ 08 мая 2012

Для дальнейшего использования: взгляните на Moka , минималистскую библиотеку функционального программирования.Из их примеров:

(List()                    # Create a new instance of moka.List
   .extend(range(1,20))    # Insert the numbers from 1 to 20
   .keep(lambda x: x > 5)  # Keep only the numbers bigger than 5
   .rem(operator.gt, 7)    # Remove the numbers bigger than 7 using partial application
   .rem(eq=6)              # Remove the number 6 using the 'operator shortcut'
   .map(str)               # Call str on each numbers (Creating a list of string)
   .invoke('zfill', 3)     # Call zfill(x, 3) on each string (Filling some 0 on the left)
   .insert(0, 'I am')      # Insert the string 'I am' at the head of the list
   .join(' '))             # Joining every string of the list and separate them with a space.

>>> 'I am 007'
0 голосов
/ 18 июля 2013

Взгляните на это .Это простой класс-оболочка для создания цепочек.И он реализовал некоторые функциональные возможности библиотеки underscore.js.Вы оборачиваете свой список, кортеж или продиктуете подчеркиванием и играете с ним, затем извлекаете из него значение, добавляя еще одно подчеркивание.

print (_([1,2,3])
       .map(lambda x: x+1)
       .reverse()
       .dict_keys(["a", "b", "c"])
       .invert()
       .items()
       .append(("this is what you got", "chaining"))
       .dict()._)

выход:

{2: 'c', 3: 'b', 4: 'a', 'this is what you got': 'chaining'}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...