4

我在同一个类中实现了几个逻辑进程。 一个类实例为每个进程获取一个生成器,并且run()推进所述生成器。在我的情况下,发电机不会结束。Python生成器函数/对象命名约定

你怎么会在下面

调用 foo_functionfoo_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) 

的典型方法discoveryauthenticationwatchdog

我如何命名功能定义生成器并以合理的方式包含生成器对象的属性?

最后只是为了踢,同名的名字将是疯了,对吧?

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

小伙子,你怎么样发表评论你认为是基于看法?毕竟它处理http://martinfowler.com/bliki/TwoHardThings.html :) – 2014-11-10 12:46:17

+1

正如书面,是的这是非常混乱。 :)你有一些具体的细节可能有助于澄清这个非常抽象的例子吗?详细信息:foo()纯粹是为了副作用而运行? self.maybe_foo = foo_if_some_attr() – spazm 2014-11-18 08:01:42

+1

你真的失去了我在这一行:self.name_me_process_generator = self.name_me_process_function() – spazm 2014-11-18 08:02:50

回答

4

你可以做的包含生成器的成员会根据函数的名称自动创建,并使用您自己设计的某种协助。例如,在我的约定中,所有的生成器都将被一个名为<function_name>_gen的成员包含。

我会打电话给函数名称作为它的责任:discovery,authenticationwatchdog是好名字。所以你只需要一种方法来自动设置:self.discovery_gen,self.authentication_genself.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) 

输出继电器

>>> 1 
>>> 2 
+0

很酷的想法一次性实例化所有生成器。 – 2014-11-20 08:19:04

+0

这是一个密切的电话。 !Raydel实际上提供了一个命名约定,@ parchment指向使用匿名对象来避免命名约定。我不喜欢这个命名约定,回避是对另一个问题的回答。因此,这个奖是共享的,对一个答复者的答案是肯定的,对另一个答复者是赏金。 – 2014-11-24 07:47:48

3

如果发电机仅在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) 
+0

有趣的问题。有趣的一面是,我能够重构我的代码以使用'iterools.izip';这与范围界定类似(保留函数ref的类和实例ref的本地变量)。不过,我仍然对原始问题的答案感兴趣。如何命名的东西,以保持发电机功能和实例明确。 – 2014-11-18 20:17:17

+0

这是一个密切的电话。@Raydel实际上提供了一个命名约定,而!羊皮纸指向使用匿名对象来避免命名约定。我不喜欢这个命名约定,回避是对另一个问题的回答。因此,这个奖是共享的,对一个答复者的答案是肯定的,对另一个答复者是赏金。 – 2014-11-24 07:48:04