Обратный вызов или генератор для обработки определенных c частей повторяющегося фрагмента кода? - PullRequest
0 голосов
/ 29 мая 2020

У меня есть несколько logi c, которые повторяются несколько раз в разных частях API, где почти все одинаково, за исключением того, что иногда приходится выполнять одну дополнительную работу, которая никогда не бывает прежней.

Для ясности, вот "форма" того, что происходит:

do_some_preparation()
for item in iterable:
    do_several_things_that_are_always_the_same()
    maybe_do_something_specific()
    # where the specific part requires:
    #   - context from the loop
    #   - context from where the whole action is started

Я вижу 2 возможных шаблона проектирования для решения этой проблемы: обратный вызов или генератор.

Обратный вызов

def handle_the_thing(..., callback=None):
    do_some_preparation()
    for item in iterable:
        do_several_things_that_are_always_the_same()
        if callback:
            callback(loop_context)

# case with no specific action
handle_the_thing(...)

# case with some specific action
def do_thing_A(): ...
handle_the_thing(..., do_thing_A)

# case with another specific action
def do_thing_B(): ...
handle_the_thing(..., do_thing_B)

Генератор

def handle_the_thing(...):
    do_some_preparation()
    for item in iterable:
        do_several_things_that_are_always_the_same()
        yield loop_context

# case with no specific action
for _ in handle_the_thing(...):
    pass

# case with some specific action
for var_from_loop in handle_the_thing(...):
    # do your thing A

# case with another specific action
for var_from_loop in handle_the_thing(...):
    # do your thing B

Итак, вопрос в том, какой из них является наиболее pythoni c и обслуживаемым / правильным?

Есть ли даже другой способ подойти к этой проблеме?

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

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

1 Ответ

0 голосов
/ 05 июня 2020

Ваше понимание совершенно верно. Генераторы кажутся способом go.

Чтобы исправить, насколько странно выглядит случай отсутствия специальных действий, я бы добавил параметр yield_contexts к handle_the_thing.

def handle_the_thing(..., yield_contexts=True):
    do_some_preparation()
    for item in iterable:
        do_several_things_that_are_always_the_same()
        if yield_contexts:
            yield loop_context

# case with no specific action -> CLEANER!
handle_the_thing(..., yield_contexts=False)

# case with some specific action -> IDENTICAL!
for var_from_loop in handle_the_thing(...):
    # do your thing A
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...