Reputation: 47
The 'while' doesn't 'break' when self.text is set to '' by the kill function.
Can someone help me make this work or suggest a better way? Need to run a string through 10+ functions quitting if string becomes '' Returning inside each function seems redundant.
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')
Clarification: Goal is to run a string through a many functions in order just once stopping if any one of the functions sets the string to "", i obviously misunderstand how 'while' work, it seems the cleanest way to me.
Upvotes: 2
Views: 5481
Reputation: 49866
Update 2: If your goal is to run a string through several functions, then your design is essentially all wrong.
Each function should NOT set a member, but instead accept a string, and return a string. Your loop should then test whether or not the value is good:
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
Update: Apparently your problem is that you don't like how while loops work. While loops only break when execution hits the test - that is, once execution enters the body, absent a break or exception, it will continue to the end of the block, and only then will the test be re-evaluated.
Probably the cleanest way to do this is to wrap self.text
with a property.
You then have three reasonable choices for the logic in your property function:
You also have another option, which is to raise an exception in kill
in much the same way as outlined above.
Your code works perfectly for me:
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
Upvotes: 4
Reputation: 7965
While it may seem redundant, you can shorten the loop if you return the string in each function. It's a more functional approach to the problem, using lazy evaluation:
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
Nice and clear with a comment.
Upvotes: 1
Reputation: 13410
You need to add a checking of text
being ''
after each function executing:
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
Output:
>>> C.run('some string')
nothing1
kill
Upvotes: 2
Reputation: 799190
Write a decorator that raises StopIteration if the attribute becomes ''.
Upvotes: 0