2012-03-08 146 views
2

当'kill'函数将self.text设置为''时,'while'不会'中断'。While循环Python类属性

有人可以帮我做这项工作或建议一个更好的方法吗? 需要运行一个字符串通过10+函数退出,如果字符串变为'' 在每个函数内返回似乎是多余的。

class Class(object): 
    def run(self, text): 
     self.text = text 

     while self.text: 
      self.nothing1() 
      self.kill() 
      self.nothing2() 
      return self.text # stop if all functions run 

    def nothing1(self): 
     print 'nothing1' 
     self.text = self.text 

    def kill(self): 
     print 'kill' 
     self.text = '' 

    def nothing2(self): 
     print 'nothing2' 
     self.text = self.text 

C = Class() 
C.run('some string') 

澄清: 目标是贯穿为了一个很多功能只是一旦停止字符串如果任意一种功能设置字符串为“”,我显然误会了如何“而”的工作,它对我来说似乎是最干净的方式。

+0

这段代码在第一次迭代时确实会中断。 – Marcin 2012-03-08 16:52:32

+0

正确,有人可以澄清为什么它不会在'杀死'中断吗? – mark 2012-03-08 17:04:57

+3

@mark为什么它应该在'kill'后停止?没有突破声明。所以它执行下面的其他函数'kill'。但是'while'的下一次迭代不会因为'self.nect == True'条件不满足而去。 – ovgolovin 2012-03-08 17:08:02

回答

0

编写一个装饰器,如果属性变为“',则会引发StopIteration。

+0

这是否意味着@decorator在10个函数之上?在装饰器上不是100%,但想法是在每个函数中不包含冗余代码。 – mark 2012-03-08 16:57:19

+0

要么是这样,要么包装装饰器中的每个调用。或者你可以做一些\ _ \ _ getattr \ _ \ _魔术,但你可能不想。 – 2012-03-08 17:05:58

2

你需要每个函数执行后增加的text''一检查:

class Class(object): 
    def run(self, text): 
     self.text = text 

     func_to_exec = [self.nothing1,self.kill,self.nothing2] 
     while True: 
      for func in func_to_exec: 
       func() 
       if not self.text: 
        break 
      else: 
       continue #executed only if no 'break' was met (starts the next iteration of `while` loop) 
      break #get out of the 'while True' loop 


    def nothing1(self): 
     print 'nothing1' 
     self.text = self.text 

    def kill(self): 
     print 'kill' 
     self.text = '' 

    def nothing2(self): 
     print 'nothing2' 
     self.text = self.text 

输出:

>>> C.run('some string') 
nothing1 
kill 
+0

谢谢!最清洁的,但我不认为'一会儿'是需要的,它应该跳出'for' – mark 2012-03-08 17:00:46

+1

@mark Hm。由于我得到的所有这些函数都必须在无限循环中执行,直到其中一个返回''''。没有? – ovgolovin 2012-03-08 17:04:30

+0

我的不好,我忘了在'while'底部加入'return self.text' – mark 2012-03-08 17:13:29

4

更新2:如果您的目标是通过多种功能来运行一个字符串,那么你的设计基本上都是错误的。

每个函数都不应该设置成员,而是接受一个字符串,并返回一个字符串。那么你的循环应该测试值是否是好的:

currstr = 'foo' 
for f in (self.nothing1, self.kill, self.nothing2): 
    tmpstr = f(currstr) 
    if not tmpstr: break # or return, or raise exception 
    currstr = tmpstr 

更新:显然,你的问题是你不喜欢的怎么while循环工作。 while循环只有在执行遇到测试时才会中断 - 也就是说,一旦执行进入正文,没有中断或异常,它将一直持续到该块的结尾,只有这样才能重新评估测试。

可能最干净的方法是将self.text换成property

然后,您必须对逻辑研究三个合理选择你的财产功能:

  1. 您可以创建在属性更改被称为处理器的系统,并且做任何你喜欢那里(包括逻辑下一个选项中的一个);
  2. 为空字符串包含一个特定的测试,并引发一个异常,并在循环外部处理它;或
  3. 在每个单独的更改中引发异常,并在循环内处理它。

您还有另外一种选择,即在kill中引发异常,其方式与上述方法大致相同。


你的代码工作完美的我:

In [139]: cpaste 
Pasting code; enter '--' alone on the line to stop or use Ctrl-D. 
:class Class(object): 
: def run(self, text): 
:  self.text = text 
: 
:  while self.text: 
:   self.nothing1() 
:   self.kill() 
:   self.nothing2() 
: 
: def nothing1(self): 
:  print 'nothing1' 
:  self.text = self.text 
: 
: def kill(self): 
:  print 'kill' 
:  self.text = '' 
: 
: def nothing2(self): 
:  print 'nothing2' 
:  self.text = self.text 
: 
:C = Class() 
:C.run('some string') 
:-- 
nothing1 
kill 
nothing2 
+0

当我得到它时,任何函数都可以将'text'设置为'''''。但我可能是错的。 – ovgolovin 2012-03-08 16:57:14

+0

@mark:这不是循环的工作方式,而是停止在kill和不运行nothing2 – mark 2012-03-08 16:57:41

+0

@mark: – Marcin 2012-03-08 17:00:00

1

虽然它可能看起来是多余的,你可以缩短循环,如果你在每个函数返回的字符串。这是一个更加功能性的方法来解决问题,使用懒惰评估:

def run(self, text): 
     self.text = text 

     func_to_exec = [self.nothing1, self.kill, self.nothing2] 
     all(func() for func in func_to_exec) # generator will evaluate func lazily 

尼斯和清晰的评论。