2010-12-03 2 views
7

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

Возможно ли связать функции с 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... 

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

Спасибо!

+0

Термин "свободно интерфейс". Dunno, почему GvR им не нравится. – 2010-12-03 06:28:51

ответ

9

Вот расширение 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 действовать полностью как список, используя collections abstract base classes. Фактически, вы могли бы подклассифицировать list, хотя он может ограничить вас от выполнения определенных действий, которые вам могут понадобиться ... и я не знаю, какое общее мнение относится к подклассам встроенных типов, таких как list.

3

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

+0

Хм, так ты говоришь, что я * не могу * определить такие функции? Я думаю, что мне нужно будет запустить jQuery и определить себя как функцию типа L ('my', 'strange', 'list'). Благодаря! – Blender 2010-12-03 06:32:20

+0

Как некий вопрос вне темы, какие специальные символы я могу использовать в имени объекта в Python?Я попробовал `$`, но интерпретатору это не нравится ... – Blender 2010-12-03 06:33:33

+0

Ну, технически вы, вероятно, могли бы, поскольку функции также являются объектами в Python. Функция может иметь собственный атрибут, который также является функцией и который можно назвать как func1.func2 (args). Но это был бы беспорядок. – Simon 2010-12-03 06:35:42

10

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

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) 
1

Для справок в будущем: посмотрите на 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

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

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'} 
Смежные вопросы