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