Функция генератора 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)