Каков идиоматический способ вызова списка функций в Python? - PullRequest
4 голосов
/ 22 мая 2009

У меня есть список функций обратного вызова, которые мне нужно вызывать при возникновении события. Это идиоматический питон?

def first_callback(m):
  print 'first ' + m

def second_callback(m):
  print 'second ' + m

lst = [first_callback, second_callback]

map(lambda x: x("event_info"),lst) #is this how you do it?

Ответы [ 4 ]

17 голосов
/ 22 мая 2009

Используйте map только для функций без побочных эффектов (например, print). То есть используйте его только для функций, которые просто что-то возвращают. В этом случае обычный цикл более идиоматичен:

for f in lst:
    f("event_info")

Редактировать : также, начиная с Python 3.0, map возвращает итератор вместо списка. Следовательно, в Python 3.0 код, приведенный в вопросе, не будет вызывать любую функцию, если только все элементы в генераторе не будут оценены явно (например, путем инкапсуляции вызова к map внутри list). К счастью, инструмент 2to3 предупредит об этом:

Файл map.py:

map(lambda x: x, range(10))

2to3-3.0 map.py вывод:

RefactoringTool: Skipping implicit fixer: buffer
RefactoringTool: Skipping implicit fixer: idioms
RefactoringTool: Skipping implicit fixer: set_literal
RefactoringTool: Skipping implicit fixer: ws_comma
--- map.py (original)
+++ map.py (refactored)
@@ -1,1 +1,1 @@
-map(lambda x: x, range(10))
+list(map(lambda x: x, list(range(10))))
RefactoringTool: Files that need to be modified:
RefactoringTool: map.py
RefactoringTool: Warnings/messages while refactoring:
RefactoringTool: ### In file map.py ###
RefactoringTool: Line 1: You should use a for loop here
3 голосов
/ 22 мая 2009

Вы также можете написать понимание списка:

[f("event_info") for f in lst]

Однако, у него есть побочный эффект возврата списка результатов.

0 голосов
/ 29 ноября 2009

Я должен спросить, действительно ли это намерение ОП. Когда я слышу «вызов списка функций», я предполагаю, что простое циклическое перемещение по списку функций и вызов каждой из них настолько очевиден, что в этом вопросе должно быть что-то еще. Например, с учетом этих двух строковых манипуляторов:

def reverse(s):
    return s[::-1]

import random
def randomcase(s):
    return ''.join(random.choice((str.upper, str.lower))(c) for c in s)

manips = [reverse, randomcase]
s = "Now is the time for all good men to come to."

# boring loop through list of manips
for fn in manips:
    print fn(s)

# more interesting chain through list of manips
s_out = s
for fn in manips:
    s_out = fn(s_out)
print s_out

Первый цикл печатает:

.ot emoc ot nem doog lla rof emit eht si woN
NOW IS THe tIMe for aLL good meN TO COme To.

Вторая цепочка вывод первой функции на вход следующей, печатая:

.oT EMoC OT NeM DOog lla RoF emit EHt SI won

Этот второй метод позволяет вам составлять более сложные функции из нескольких простых.

0 голосов
/ 28 ноября 2009

Если у вас есть динамически созданный список простых функций, это хорошо:

для функции в list_of_functions: Функция (your_argument_here)

Но если вы используете ООП, и некоторые классы должны знать, что какое-то событие происходит (как правило, изменяется), подумайте о введении шаблона проектирования Observer: http://en.wikipedia.org/wiki/Observer_pattern,

Введение шаблона означает рефакторинг рабочего кода к этому шаблону (и остановку, когда код выглядит хорошо, даже если не был введен целый паттер), подробнее в "Рефакторинг на шаблоны" Кериевский.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...