2012-02-16 79 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

相关问题