2012-02-16 80 views
4

這是一個Python風格的問題 - 我的Python代碼起作用,我只是在尋找一種編碼約定的建議,以使代碼更易於閱讀/理解/調試。在Python中表達窗口的分層分組有什麼好方法?

具體來說,我正在研究一個Python類,它允許調用者將小部件添加到自定義GUI。爲了設置GUI,用戶可以編寫一個方法,將小部件(命名或匿名)添加到小部件區域,以便小部件形成一個樹(在GUI中很常見)。

爲了允許用戶設置小部件樹而不必爲每個容器小部件命名(然後每次添加小部件時都明確引用該父小部件),我的API支持一個「父窗口小部件堆棧」。當聲明一個容器小部件時,用戶可以指定將這個小部件推送到這個堆棧上,然後默認情況下,任何其他小部件(沒有明確指定父容器)將被添加到堆棧頂部的父容器中。下面是我的意思一個簡單的例子:

def SetupGUI(self): 
    self.AddWidget(name="root", type="container", push=True) 

    self.AddWidget(type="container", push=True) 
    for i in range(0,8): 
     self.AddWidget(name="button%i"%i, type="button") 
    self.PopParentWidget() # pop the buttons-container off the parents-stack 

    self.AddWidget(type="container", push=True) 
    for i in range(0,8): 
     self.AddWidget(name="slider%i"%i, type="slider") 
    self.PopParentWidget() # pop the sliders-container off the parents-stack 

    self.PopParentWidget() # pop the container "root" off the parents-stack 

這是方便,但我發現,當GUI層次結構中變得更復雜,它開始變得難以分辨哪個調用self.PopParentWidget()對應於哪個容器小部件。很容易放入太多或太少的數據,最終會在GUI中產生非常有趣但意想不到的結果。

所以我的問題是,迫使PopParentWidget()採取明確的小部件名稱(我想避免,因爲我不想命名每個容器小部件),有什麼我可以做的讓代碼中的push/pop配對更加明顯?

在C/C++中,我會使用縮進來做到這一點,但是對於Python我不允許這樣做。比如,我很想能夠做到這一點:

def SetupGUI(self): 
    self.AddWidget(name="root", type="container", push=True) 
     self.AddWidget(type="container", push=True) 
     for i in range(0,8): 
      self.AddWidget(name="button%i"%i, type="button") 
     self.PopParentWidget() # pop the buttons-container off the parents-stack 
     self.AddWidget(type="container", push=True) 
     for i in range(0,8): 
      self.AddWidget(name="slider%i"%i, type="slider") 
     self.PopParentWidget() # pop the sliders-container off the parents-stack 
     self.PopParentWidget() # pop the container "root" off the parents-stack 

...但是Python會拋出了一個IndentationError如果我得到創造性這樣。

+0

我只是很高興,Python不會讓你這樣做。如果人們開始做後續工作,即使是單個項目也要保持代碼風格一致,這將是一場噩夢。 – jsbueno 2012-02-17 02:12:13

回答

6

這種情況 - 你有一對相反的操作 - 要求a context manager。不要將容器小部件明確地推入/彈出堆棧,而是將容器的子項包裝在with塊中。你在這裏顯示的代碼頂部的基礎上,實現這一點的,就像這樣

@contextlib.contextmanager 
def container(self, name=None): 
    self.AddWidget(name=name, type='container', push=True) 
    yield 
    self.PopParentWidget() 

(文檔爲contextlib.contextmanager)。

SetupGUI方法就變成了:

def SetupGUI(self): 
    with self.container(name='root'): 
     with self.container(): 
      for i in range(0,8): 
       self.AddWidget(name='button%i' % i, type='button') 
     with self.container(): 
      for i in range(0,8): 
       self.AddWidget(name='slider%i' % i, type='slider') 

正如你所看到的,嵌套是從壓痕清晰,而且也沒有必要手動push和pop。

+0

非常好,謝謝!我想有可能是這樣的:) – 2012-02-16 03:37:24

相關問題