No "side effect" assignment!

Discussion in 'Python' started by Tobiah, Sep 14, 2003.

  1. Tobiah

    Tobiah Guest

    Ok,

    I miss the idiom that my other languages use,
    something like:


    while( foo = getmore()){
    process(foo);
    }


    I can't seem to do this in python without gagging:

    foo = getmore()
    while foo:
    process(foo)
    foo = getmore()


    Is that what ppl do? The manual sez that this is
    so that newbs won't do:

    if foo = bar:
    process()

    thinking that they are checking for equality.
    I feel that in a few ways python suffers by catering
    to the uninitiated. Usually however, there are
    great workarounds (or even plain better ways to do the job),
    which I am hopeful will be yielded by the list, as has
    been it's record thus far to do.

    Thanks,

    Tobiah
     
    Tobiah, Sep 14, 2003
    #1
    1. Advertising

  2. Tobiah

    Dave Kuhlman Guest

    Tobiah wrote:

    [snip]
    >
    >
    > I can't seem to do this in python without gagging:
    >
    > foo = getmore()
    > while foo:
    > process(foo)
    > foo = getmore()


    Then test your gag reflex on the following:

    while 1:
    foo = getmore()
    if not foo:
    break
    process(foo)

    Slips down pretty smoothly with me.

    [snip]

    Dave

    --
    Dave Kuhlman
    http://www.rexx.com/~dkuhlman
     
    Dave Kuhlman, Sep 14, 2003
    #2
    1. Advertising

  3. Tobiah

    Tobiah Guest

    Ack!!! (slight gag reflex) :)

    That's actually more lines, even if more readable.

    Ok, my perl roots are showing, but I was thinking
    of putting the following function into my standard
    module:

    def eq(thingy):
    global _
    _ = thingy
    return _



    Having done that, I can now say:

    while eq(getmore()):
    process(_)


    It seems to me that adding support for the side effect
    assignment would not break any existing scripts. Gee,
    they did it for += ;)

    Thanks,

    Tobiah

    > Then test your gag reflex on the following:
    >
    > while 1:
    > foo = getmore()
    > if not foo:
    > break
    > process(foo)
    >
    > Slips down pretty smoothly with me.
    >
    > [snip]
    >
    > Dave
    >
     
    Tobiah, Sep 14, 2003
    #3
  4. Tobiah

    John Roth Guest

    "Tobiah" <> wrote in message
    news:...
    > Ok,
    >
    > I miss the idiom that my other languages use,
    > something like:
    >
    >
    > while( foo = getmore()){
    > process(foo);
    > }
    >
    >
    > I can't seem to do this in python without gagging:
    >
    > foo = getmore()
    > while foo:
    > process(foo)
    > foo = getmore()
    >
    >
    > Is that what ppl do? The manual sez that this is
    > so that newbs won't do:
    >
    > if foo = bar:
    > process()
    >
    > thinking that they are checking for equality.
    > I feel that in a few ways python suffers by catering
    > to the uninitiated. Usually however, there are
    > great workarounds (or even plain better ways to do the job),
    > which I am hopeful will be yielded by the list, as has
    > been it's record thus far to do.


    While one of Guido's reasons for not including assignment
    as an expression was to avoid errors (and that's not always
    a novice error,) Python provides similar functionality in the
    'for' statement. In C, C++ and Java, 'for' is basically
    syntactic sugar around a loop, in Python, it actually does
    an assignment of the next element of a sequence.

    Your example could be:

    for foo in getmore:
    process(foo)

    as long as getmore is either a sequence or implements the
    iterator protocol.

    This isn't a total replacement for assignment as an expression,
    but it does cover the overwhelming majority of use cases.

    John Roth


    >
    > Thanks,
    >
    > Tobiah
    >
     
    John Roth, Sep 14, 2003
    #4
  5. Tobiah

    Sean Ross Guest

    Sean Ross, Sep 15, 2003
    #5
  6. Tobiah> Ack!!! (slight gag reflex) :)
    Tobiah> That's actually more lines, even if more readable.

    Tobiah> Ok, my perl roots are showing, but I was thinking
    Tobiah> of putting the following function into my standard
    Tobiah> module:

    Tobiah> def eq(thingy):
    Tobiah> global _
    Tobiah> _ = thingy
    Tobiah> return _



    Tobiah> Having done that, I can now say:

    Tobiah> while eq(getmore()):
    Tobiah> process(_)

    You're right -- your Perl roots are showing.

    How about this instead:

    def make_generator(func):
    while x = func():
    yield x

    for val in make_generator(getmore):
    process(val)

    --
    Andrew Koenig,
     
    Andrew Koenig, Sep 15, 2003
    #6
  7. Andrew Koenig wrote:

    > How about this instead:
    >
    > def make_generator(func):
    > while x = func():

    ^^^^^^^^^^

    Not too likely in Python :).

    --
    Erik Max Francis && && http://www.alcyone.com/max/
    __ San Jose, CA, USA && 37 20 N 121 53 W && &tSftDotIotE
    / \ Youth is a period of missed opportunities.
    \__/ Cyril Connolly
     
    Erik Max Francis, Sep 15, 2003
    #7
  8. Tobiah

    Tobiah Guest

    Erik Max Francis wrote:
    > Andrew Koenig wrote:
    >
    >
    >>How about this instead:
    >>
    >> def make_generator(func):
    >> while x = func():

    >
    > ^^^^^^^^^^
    >
    > Not too likely in Python :).
    >


    Heh! My point exactly :)
     
    Tobiah, Sep 15, 2003
    #8
  9. Tobiah

    Asun Friere Guest

    Dave Kuhlman <> wrote in message news:<bk2okk$nrhg9$-berlin.de>...
    > Tobiah wrote:
    >
    > [snip]
    > >
    > >
    > > I can't seem to do this in python without gagging:
    > >
    > > foo = getmore()
    > > while foo:
    > > process(foo)
    > > foo = getmore()

    >
    > Then test your gag reflex on the following:
    >
    > while 1:
    > foo = getmore()
    > if not foo:
    > break
    > process(foo)
    >
    > Slips down pretty smoothly with me.
    >
    > [snip]
    >
    > Dave


    I am alone in feeling some slight unease at the sight of "while 1: ...
    break"? I know this is considered somewhat pythonic, but apart from
    the fact that there is only a single assignment statement is there
    really any advantage to be gained by doing it this way? It seems to
    be trading one aesthetic disadvantage for another, and imho, a
    marginally less legible one.

    In terms of pandering to newbies, I think the requirement that loop
    conditions be expressions is much more squarely aimed at experienced
    programmers, who would otherwise be tempted to write unintelligible
    code by placing too much of the programs logic withing the loop
    condition.
     
    Asun Friere, Sep 15, 2003
    #9
  10. Tobiah

    Duncan Booth Guest

    Tobiah <> wrote in
    news::

    > I can't seem to do this in python without gagging:
    >
    > foo = getmore()
    > while foo:
    > process(foo)
    > foo = getmore()
    >
    >
    > Is that what ppl do?


    I don't know about ppl, but Python programmers have a variety of ways of
    structuring this code. The one that I think is simplest, but is often
    overlooked is to use the builtin function 'iter'. It won't exactly replace
    the code you have above, since your loop terminates as soon as getmore()
    returns anything false (None, 0, False, '' would all terminate it). If
    however you know the exact value to indicate termination (I'll guess
    getmore() returns None when its done), you can write your loop:

    for foo in iter(getmore, None):
    process(foo)

    If instead of a simple function call you had a more complex expression (say
    getmore took a file as an argument), you might consider a lambda:

    for foo in iter(lambda: getmore(aFile), None):
    process(foo)


    --
    Duncan Booth
    int month(char *p){return(124864/((p[0]+p[1]-p[2]&0x1f)+1)%12)["\5\x8\3"
    "\6\7\xb\1\x9\xa\2\0\4"];} // Who said my code was obscure?
     
    Duncan Booth, Sep 15, 2003
    #10
  11. Tobiah

    Peter Hansen Guest

    Asun Friere wrote:
    >
    > Dave Kuhlman wrote:
    > > while 1:
    > > foo = getmore()
    > > if not foo:
    > > break
    > > process(foo)

    >
    > I am alone in feeling some slight unease at the sight of "while 1: ...
    > break"? I know this is considered somewhat pythonic, but apart from
    > the fact that there is only a single assignment statement is there
    > really any advantage to be gained by doing it this way? It seems to
    > be trading one aesthetic disadvantage for another, and imho, a
    > marginally less legible one.


    There is a distinct advantage in the above, over the form with
    a duplicated line, and it's nothing to do with aesthetics. Sure,
    they both may be ugly to you (but they feel quite simple and thus
    elegant to some experienced Python programmers), but the real issue
    is that the one has the duplicated assignment and is therefore prone
    to maintenance problems. This fact alone far outweighs any aesthetic
    consideration, and wholly justifies the above form.

    If you are really offended, use a wrapper of some kind as others have
    shown.

    -Peter
     
    Peter Hansen, Sep 15, 2003
    #11
  12. (Asun Friere) writes:

    > I am alone in feeling some slight unease at the sight of "while 1: ...
    > break"? I know this is considered somewhat pythonic, but apart from
    > the fact that there is only a single assignment statement is there
    > really any advantage to be gained by doing it this way? It seems to
    > be trading one aesthetic disadvantage for another, and imho, a
    > marginally less legible one.


    While I agree with you, I don't think I'd bother with changing thel
    language now to fix it. If I were writing a new language I'd prefer a
    loop-and-a-half structure something like this:

    repeat:
    stuff
    while test:
    stuff

    I'd really prefer something like the above without the second colon.
    While it's nice to have the condition dedented for readability, it
    isn't really starting a new block. At any rate, I don't think adding
    this to the current language is worth it, so I'll keep using "while 1:
    break" structures and translating to the above in my head.

    --
    Christopher A. Craig <>
    "So we who are many, are one body in Christ, and individually members
    one of another." Romans 12:5 (NASB)
     
    Christopher A. Craig, Sep 15, 2003
    #12
  13. Tobiah

    John J. Lee Guest

    Tobiah <> writes:

    > Erik Max Francis wrote:
    > > Andrew Koenig wrote:
    > >
    > >>How about this instead:
    > >>
    > >> def make_generator(func):
    > >> while x = func():

    > > ^^^^^^^^^^
    > > Not too likely in Python :).
    > >

    >
    > Heh! My point exactly :)


    def f(): return raw_input()

    for x in iter(f, ""):
    print x


    If you want to be more vague about the sentinel (a bad idea, and
    equivalent to your Perl example), I suppose you could use something
    obscure like this:

    class FalsehoodSentinel:
    def __cmp__(self, other): return int(bool(other))
    falsehoodsentinel = FalsehoodSentinel()


    and then:

    def f(): return raw_input()

    for x in iter(f, falsehoodsentinel):
    print x


    So that *any* false value from f will end the for loop. Don't do
    that, though -- explicit is better...

    Of course, most of the time, having written your program Pythonishly,
    not Perlishly, you'll have iterators in the first place, and won't
    need to turn them into an iterator by hand.


    John
     
    John J. Lee, Sep 15, 2003
    #13
  14. Tobiah

    Terry Reedy Guest

    "John J. Lee" <> wrote in message
    news:...
    > def f(): return raw_input()
    >
    > for x in iter(f, ""):
    > print x


    Nice -- I keep forgetting about iter() -- except that the wrapper
    adds nothing that I can see.

    >>> for l in iter(raw_input, ''): print '*', l, '*'

    ....
    aksjf
    * aksjf *
    jslfkj
    * jslfkj *

    >>>


    Terry J. Reedy
     
    Terry Reedy, Sep 16, 2003
    #14
  15. Tobiah

    Martin Maney Guest

    Asun Friere <> wrote:
    > In terms of pandering to newbies, I think the requirement that loop
    > conditions be expressions is much more squarely aimed at experienced
    > programmers, who would otherwise be tempted to write unintelligible
    > code by placing too much of the programs logic withing the loop
    > condition.


    Uhm, no. *Experienced* programmers know better than to take usch
    things to excess, unless the code is being written for a obfuscated
    code contest. As is so often the case, it's those difficult
    in-betweeners, no longer innocent by virtue of ignorance, not yet
    grown wise enough to eschew the merely clever, who bollix it all up for
    the rest of us.

    --
    Threaten not the comic with your lawyers' bluster,
    all toothless to supress parody and satire;
    for you will not amuse him, but you may inspire him.
    (me, inspired by http://www.netfunny.com/rhf/jokes/01/Apr/mcrhf.html)
     
    Martin Maney, Sep 18, 2003
    #15
  16. Tobiah

    Martin Maney Guest

    Sean Ross <> wrote:
    > If you must use assignments in expressions, you might find the following
    > recipes useful:
    > http://aspn.activestate.com/ASPN/Cookbook/Python/Recipe/202234


    Did I forget about this one or is it in fact new? It is, as the author
    says, an ugly hack at the implementation level, but that seems to be
    its only drawback. It doesn't use any hidden state that could be
    altered unexpectedly, and is only a minor eyesore; those who worry
    about accidentally writing an assignment in place of an equality test
    will consider that last to be a feature, of course. Perhaps it could
    be improved, slightly, by being renamed to "let"? <evil grin>

    > http://aspn.activestate.com/ASPN/Cookbook/Python/Recipe/66061


    The hope of obliterating this recipie is IMO the strongest argument in
    favor of adding operator= to Python. I can think of no reason to
    prefer this to 202234 aside from the chance that the language
    implementation detail used in the latter's implementation could
    conceivably go away someday.

    Short form: 66061 Considered Harmful. What, you thought it was just a
    coincidence it had all those sixes in its number?

    --
    People make secure systems insecure because
    insecure systems do what people want and
    secure systems don't. -- James Grimmelmann
     
    Martin Maney, Sep 18, 2003
    #16
  17. "Martin Maney" <> wrote in message
    news:bkbfh1$8il$14.net...
    > Sean Ross <> wrote:
    > > If you must use assignments in expressions, you might find the following
    > > recipes useful:
    > > http://aspn.activestate.com/ASPN/Cookbook/Python/Recipe/202234

    >
    > Did I forget about this one or is it in fact new? It is, as the author
    > says, an ugly hack at the implementation level, but that seems to be
    > its only drawback.


    I think that the other drawback is that it only works at the top level of a
    module. If you are inside a function or method then the locals() (f_locals)
    dictionary is still writeable but it has no effect on the namespace it
    represents.

    So ...

    import sys
    def set(**kw):
    assert len(kw)==1

    a = sys._getframe(1)
    a.f_locals.update(kw)
    return kw.values()[0]

    def main():
    A=range(10)

    while set(x=A.pop()):
    print x

    main()

    .... prints 0,0,0,0,0,0 etc instead of what you want.

    I guess you might call "a.f_locals.update(kw)" a no-(side)-effect assignment
    ;)

    Paul
     
    Paul Paterson, Sep 19, 2003
    #17
  18. Tobiah

    Martin Maney Guest

    Paul Paterson <> wrote:
    > I think that the other drawback is that it only works at the top level of a
    > module.


    Yeah, it comes back to me now. So there's still nothing but ugly
    and/or dangerous workarounds when you need to use a function's result
    in a conditional as well as later on. Pytho is such a pleasant
    language 95% of the time that the nastiness of the corner cases seems
    worse than they rationally warrant - or maybe not, since these warts
    tend to drop me out of flow and cost a lot more time than just
    remebering the way(s) to hack around them.

    > I guess you might call "a.f_locals.update(kw)" a no-(side)-effect assignment


    Sure 'nuff. Pity, it was otherwise quite a nice answer to what seems
    to be an endlessly recurring issue.

    --
    Although we may never know with complete certainty the identity
    of the winner of this year's presidential election, the identity
    of the loser is perfectly clear. It is the nation's confidence
    in the judge as an impartial guardian of the law.
    - Justice John Paul Stevens, from his dissenting opinion Dec 12, 2000
     
    Martin Maney, Sep 19, 2003
    #18
    1. Advertising

Want to reply to this thread or ask your own question?

It takes just 2 minutes to sign up (and it's free!). Just click the sign up button to choose a username and then you can ask your own questions on the forum.
Similar Threads
  1. John E. Jardine

    s/// has apparent side effect on grep()

    John E. Jardine, Apr 12, 2004, in forum: Perl
    Replies:
    2
    Views:
    473
    John Jardine
    Apr 13, 2004
  2. =?Utf-8?B?R2lhbmNhcmxv?=

    Strange side effect with events

    =?Utf-8?B?R2lhbmNhcmxv?=, Jan 13, 2005, in forum: ASP .Net
    Replies:
    2
    Views:
    414
    =?Utf-8?B?R2lhbmNhcmxv?=
    Jan 13, 2005
  3. Roedy Green
    Replies:
    18
    Views:
    997
    Raymond DeCampo
    Sep 25, 2005
  4. DaKoadMunky
    Replies:
    1
    Views:
    405
    Ron Natalie
    Aug 18, 2004
  5. Sensorflo
    Replies:
    3
    Views:
    637
    Ron Natalie
    Aug 19, 2004
Loading...

Share This Page