Feedback on Until recipe

Paul McGuire ptmcg at austin.rr.com
Wed Apr 25 21:57:38 EDT 2007


On Apr 24, 11:08 am, Thomas Nelson <t... at mail.utexas.edu> wrote:
> Occasionally someone posts to this group complaining about the lack of
> "repeat ... until" in python.  I too have occasionally wished for such
> a construct, and after some thinking, I came up with the class below.
> I'm hoping to get some feedback here, and if people besides me think
> they might use it someday, I can put it on the python cookbook.  I'm
> pretty happy with it, the only ugly thing is you have to use a
> lambda.  Ideally i'd like to just see
> while Until(i<3)
> but that doesn't work.
> Please tell me what you think, and thanks for your time.
>
> Tom
>
> class Until:
>     """
>     >>> i = 0
>     >>> while Until(lambda: i<3):
>     ...     print "hello"
>     ...     i += 1
>     hello
>     hello
>     hello
>     >>> while Until(lambda: i<2):  #note i still equals 3 here
>     ...     print "hello"
>     hello
>     """
>     yet = True
>     def __init__(self, mybool):
>         if self.__class__.yet or mybool():
>             self.__class__.yet = False
>             self.ans = True
>         else:
>             self.__class__.yet = True
>             self.ans = False
>
>     def __nonzero__(self):
>             return self.ans

Class-level "yet" variable not a good idea.  Loops can be nested:

i = 0
# this should loop once, since test is logically at the end of the
loop
while Until(lambda : i < 0 ):
    print "hello"
    i += 1
    j = 0
    while Until(lambda : j < 0 ):
        print "byebye"
        j += 1

This loops forever.

After tinkering with this a bit, I can see why you need a class
variable.  In your outer loop, "Until(lambda : i < 0)" is evaluated
every time around the loop, creating a new Until object, so you can't
preserve looping state in the object, you have to do it in the class.

I used your idea to create an instance-level Until that survives
looping, but the requirements for construction are still onerous.  In
essence, the instance-level util defers the break-on-condition by one
loop iteration.

class Until:
    """
    >>> i = 0
    >>> while Until(lambda: i<3):
    ...     print "hello"
    ...     i += 1
    hello
    hello
    hello
    >>> while Until(lambda: i<2):
    ...     print "hello"
    hello
    """
    def __init__(self, mybool):
        self.lastTest = True
        self.mybool = mybool

    def __nonzero__(self):
        ret,self.lastTest = self.lastTest,self.mybool()
        return ret

i = 0
uCond1 = Until(lambda : i < 0 )
uCond2 = Until(lambda : j < 0 )
while uCond1:
    print "hello"
    i += 1
    j = 0
    while uCond2:
        print "byebye"
        j += 1

-- Paul




More information about the Python-list mailing list