Ifs and assignments

John Allsup pydev at allsup.co
Thu Jan 2 16:44:06 EST 2014


The point of my original post was that, whilst C's
   if( x = 2 ) { do something }
and
   if( x == 2 ) { do something }
are easy to confuse, and a source of bugs, having a construct like follows:

if x == 2:
	do something # what happens at present
if testFunc() as x:
	do something with x

using the 'as' syntax that appears with 'with' and 'except', would allow
for the advantages of C style assignments in conditionals but without 
the easy confusion, since here the syntax is significantly different 
between assignment and equality testing (rather than a character apart 
as happens with C).

This occurs further down in my original post (past the point where you 
inserted your reply).

Another post suggested a workaround by defining a 'pocket' class, for 
which I am grateful.

John


On 02/01/2014 19:27, Gary Herron wrote:
> On 01/02/2014 09:20 AM, John Allsup wrote:
>> Hi,
>>
>> This is my debut on this list.
>>
>> In many languages, such as C, one can use assignments in conditionals
>> and expressions.  The most common, and useful case turns up when you
>> have if/else if/else if/else constructs. Consider the following
>> non-working pseudoPython.
>>
>> import re
>> r1 = re.compile("hello (\d)")
>> r2 = re.compile("world([!?])")
>>
>> w = "hello world!"
>>
>> if m = r1.search(w):
>
> This kind of thing in C/C+ has always been the source of much confusion
> and potential errors, because the construct is so similar to an "=="
> test.  Python does not replicate this potential for confusion. Instead,
> we use two lines of code, an assignment and then the test.   If you find
> that extra line of code inconvenient than at least you can take comfort
> in the fact that it is clearer code.  If you are still not convinced,
> ... then sorry, that's just the way Python is.
>
> Gary Herron
>
>
>>     handleMatch1(m)
>> elif m = r2.search(w):
>>     handleMatch2(m)
>> else:
>>     print("No match")
>>
>> If the regular expressions are complex, running them multiple times
>> (once to test, another to capture groups) isn't ideal.  On the other
>> hand, at present, one has to either do:
>>
>> m = r1.search(w)
>> if m:
>>     handleMatch1(m)
>> else:
>>     m = r2.search(w)
>>     if m:
>>         handleMatch2(m)
>>     else:
>>         print("No match")
>>
>> if not running unnecessary matches, yet capturing groups in the event
>> of a successful match, is what is desired.
>>
>> If there are multiple tests, the indentation gets silly.  This arises
>> because having removed the ability to assign in an expression, there
>> is no way to save the result of a function call that is used in a
>> conditional at all.
>>
>> I am aware that this facility in C is a source of bugs, = being only a
>> typo away from the more common ==.  With exceptions and contexts, we
>> have:
>>
>> with open("file") as f:
>>     doSomethingWith(f)
>>
>> try:
>>     trySomething()
>> except SomethingRandomGoingWrong as e:
>>     lookAtException(e)
>>
>> What I am wondering is why not use a similar syntax with if, so that
>> one could do
>>
>> if r1.search(w) as m:
>>     g = m.groups()
>>     print(g[1])
>>
>> This would remove the risk of errors by typos since the syntax for
>> equality testing (if x == y:) is completely different from that for
>> assigning in a conditional (which would look like 'if y as x:'
>>
>> Related would be to have Nonetype work with contexts such that
>>
>> with None as x:
>>     doStuff(x)
>>
>> would do nothing.  This would allow things like:
>>
>> with maybeGetSomething as x:
>>     doStuff(x)
>>
>> to call doStuff(x) within a context of maybeGetSomething returns
>> something, or do nothing if nothing is returned.  (Adding an else-like
>> keyword to with, or possibly using else in that context, would allow
>> one to process a non-None object if returned, or else do something in
>> response to a None object being returned by the maybeGetSomething.)
>>
>> Just a thought.
>>
>> Or what is the current 'Pythonic' way to do something like:
>>
>> if x = func1():
>>     do1(x)
>> elif x = func2():
>>     do2(x)
>> elif x = func3():
>>     do3(x)
>> elif x = func4():
>>     do4(x)
>> else:
>>     do5()
>>
>> where each of func1,func2,func3,func4 have side effects so that func2
>> is tested if and only if func1 returns a false value, func1 must be
>> called only once, and what is returned from func1 must be available to
>> the code inside the if block?
>>
>>
>> John
>>
>




More information about the Python-list mailing list