Функция генератора Python / соглашение об именах объектов

У меня есть несколько логических процессов, реализованных в одном классе. Экземпляр класса получает генератор для каждого процесса, и run() авансы указанных генераторов. В моем случае генераторы не заканчиваются.

Как бы вы назвали foo_function и foo_object в приведенном ниже коде

class C(threading.Thread):
    def foo_function(self):
        """ generator *function*,
            logical process foo """
        while True:
            # some state checks
            if self.some_attr:
                # side-effects here
                pass
            yield

    def __init__(self):
        # generator *object*
        # i.e. process instance
        self.foo_object = self.foo_function()  # <- here

    def run(self):
        while True:
            next(self.foo_object)
            next(self.another_object)
            if xxx:
                next(self.yet_another_object)

Типичные процессы discovery, authentication, watchdog, так далее.

Как я могу назвать функцию, которая определяет генератор и атрибут, который содержит объект генератора разумным способом?

Наконец только для ударов, одноименное имя было бы безумным, правильно?

class C:
    def foo(self):
        yield 1; yield 2
    def __init__(self):
        self.foo = self.foo()

c = C()            
type(C.foo) is function
type(c.foo) is generator

2 ответа

Решение

Вы можете сделать так, чтобы члены, содержащие генераторы, создавались автоматически из имени функции, используя какое-то соглашение, разработанное вами самим. Например, в моем соглашении все генераторы будут содержаться членом под названием: <function_name>_gen,

Я бы назвал имя функции как ее ответственность: discovery, authentication а также watchdog хорошие имена. Так что вам нужен только способ автоматической установки: self.discovery_gen, self.authentication_gen а также self.watchdog_gen,

Пример кода:

class C:

    def discovery(self):
        yield 1; yield 2

    # Register all the functions for wich you want to have a generator
    # object.
    REGISTERED_GEN_FUNCTIONS = [discovery]

    def __init__(self):

        for func in self.REGISTERED_GEN_FUNCTIONS:
            name = func.__name__
            # All generators objects will be called <function_name>_gen.
            setattr(self, "{0}_gen".format(name), getattr(self, name)())

a = C()
for i in a.discovery_gen:
    print(i)

Ouput

>>> 1
>>> 2 

Если генераторы доступны только внутри run Метод, который вы можете сделать что-то вроде этого:

class C:
    def a_process(self):
        while True: yield

    def another_process(self):
        while True: yield

    def run(self):
        # Use itertools.izip in python 2
        for _ in zip(a_process(), another_process()):
            pass

Вот, zip и цикл for создаст и улучшит генераторы автоматически. Таким образом, вам не нужно отслеживать их.

Если вам нужен доступ к генераторам за пределами run Метод, вы можете создать упорядоченный словарь генераторов (в случае, если генераторы должны быть продвинуты в определенном порядке):

from collections import OrderedDict

class C:
    # Processes here

    def __init__(self):
        self.generators = OrderedDict()
        for gn in ('a_process', 'another_process'):
            self.generators[gn] = getattr(self, gn)()

    def run(self):
        while True:
            for g in self.generators.values():
                next(g)

Обращаясь только к заголовку "Соглашение об именах функций генератора Python".

Лично мне нравится называть функции генератора как "yield_items". Код читается естественным образом, а ключевое слово yield указывает, что оно выводит объект генератора.

def yield_squares(iter_max=10):
    for i in range(iter_max):
        yield i**2

squares = yield_squares()
for square in squares:
    print(square)
Другие вопросы по тегам