- **Python**
(*http://www.velocityreviews.com/forums/f43-python.html*)

- - **Arithmetic with Boolean values**
(*http://www.velocityreviews.com/forums/t949937-arithmetic-with-boolean-values.html*)

Arithmetic with Boolean valuesI have gotten used to switching back and forth between Boolean algebra and numerical values. Python generally makes this quite easy. I just found a case that surprises me.
Here is what I want to accomplish: I want to process a list. If the length of the list L is odd, I want to process it once. If len(L) is even, I want to process it twice. I thought I would set up a loop as follows: for x in range(1 + not(len(L) % 2)): # Do stuff This provoked a SyntaxError. I investigated this further with my interpreter (ipython). In [1]: L = range(5) In [2]: L Out[2]: [0, 1, 2, 3, 4] In [3]: len(L) Out[3]: 5 In [4]: len(L) % 2 Out[4]: 1 In [5]: not(1) Out[5]: False In [6]: not(len(L) % 2) Out[6]: False In [7]: 1 + not(len(L) % 2) ------------------------------------------------------------ File "<ipython console>", line 1 1 + not(len(L) % 2) ^ SyntaxError: invalid syntax So as you can see, every thing is working fine until I attempt to add 1 andFalse. However: In [8]: 0 == False Out[8]: True In [9]: 1 == True Out[9]: True So, 0 and False do pass an equivalency test, as do 1 and True. Furthermore: In [10]: 1 + (len(L) % 2 == 0) Out[10]: 1 Why is using a logical "not" function, as shown in [7], returning a different result than the test for equivalency as shown in [10]? Of course I'm just going to use [10] in my program, but I'd like to understand the reason that I'm getting that SyntaxError. I've been reading Pythonstyle guides, and at least one of them states a preference for using the "not" syntax over the "== 0" syntax. I'm using Python 2.7, in case it matters. |

Re: Arithmetic with Boolean valuesOn Sun, Aug 12, 2012 at 8:30 AM, John Ladasky
<john_ladasky@sbcglobal.net> wrote: > In [7]: 1 + not(len(L) % 2) > ------------------------------------------------------------ > File "<ipython console>", line 1 > 1 + not(len(L) % 2) > ^ > SyntaxError: invalid syntax This appears to be a limitation of the parser; it's trying to interpret "not" as a binary operator. 1 + (not(len(L) % 2)) Works just fine with parentheses to enforce the correct interpretation. This also works in Python 3.2, fwiw (except that you need list(range(5)) to create the sample list). ChrisA |

Re: Arithmetic with Boolean valuesOn Sat, Aug 11, 2012 at 3:30 PM, John Ladasky
<john_ladasky@sbcglobal.net> wrote: <snip> > for x in range(1 + not(len(L) % 2)): > # Do stuff > > This provoked a SyntaxError. I investigated this further with my interpreter (ipython). <snip> > In [5]: not(1) > Out[5]: False > > In [6]: not(len(L) % 2) > Out[6]: False > > In [7]: 1 + not(len(L) % 2) > ------------------------------------------------------------ > File "<ipython console>", line 1 > 1 + not(len(L) % 2) > ^ > SyntaxError: invalid syntax <snip> > Why is using a logical "not" function, as shown in [7], returning a different result than the test for equivalency as shown in [10]? Note that, in Python, `not` is an unary operator (it's a language keyword in fact), as opposed to a function: Python 2.7.2 (default, Jun 20 2012, 16:23:33) >>> len("abc") 3 >>> # functions are first-class entities in Python, so we can reference them >>> len <built-in function len> >>> not(1) False >>> # but `not` isn't a function >>> not File "<stdin>", line 1 not ^ SyntaxError: invalid syntax >>> # hence why we don't need to call it >>> not 1 False The parentheses in `not(foo)` are just grouping the `foo` subexpression; they're not indicating a function call. Therefore, in idiomatic Python, such parentheses are omitted whenever possible (which is the majority of the time), and when they are absolutely necessary, a space is included before the opening paren, because we're not making a function call. Thus, you're simply running into an operator precedence issue, which, as Chris A. explained, can be remedied by adding grouping parens around the entire `not` expression; e.g. `(not foo)` Cheers, Chris R. |

Re: Arithmetic with Boolean valuesOn 8/11/2012 7:13 PM, Chris Angelico wrote:
> On Sun, Aug 12, 2012 at 8:30 AM, John Ladasky > <john_ladasky@sbcglobal.net> wrote: >> In [7]: 1 + not(len(L) % 2) >> ------------------------------------------------------------ >> File "<ipython console>", line 1 >> 1 + not(len(L) % 2) >> ^ >> SyntaxError: invalid syntax > > This appears to be a limitation of the parser; it's trying to > interpret "not" as a binary operator. I think not. It is lower precedence than all arithmetic operators. The following is worth knowing about and occasionally reviewing. http://docs.python.org/py3k/referenc...s.html#summary () around % is not needed; not len(L) % 2 works same. So parser sees 1 + not len(L) % 2 with + given higher precedence than not, So it parses as (1 + not) and croaks, as indicated by caret. (We humans see that that is impossible and may boost the precedence in context.) > 1 + (not(len(L) % 2)) == 1 + (not len(L) % 2) > > Works just fine with parentheses to enforce the correct interpretation. > > This also works in Python 3.2, fwiw (except that you need > list(range(5)) to create the sample list). -- Terry Jan Reedy |

Re: Arithmetic with Boolean valuesOn Sun, Aug 12, 2012 at 10:25 AM, Terry Reedy <tjreedy@udel.edu> wrote:
> On 8/11/2012 7:13 PM, Chris Angelico wrote: >> This appears to be a limitation of the parser; it's trying to >> interpret "not" as a binary operator. > > I think not. It is lower precedence than all arithmetic operators. > (We humans see that that is impossible and > may boost the precedence in context.) Ah, I stand corrected. And once again, I kinda expected Python to follow the rules of my mental parser :) Anyway, point stands that parens will fix the issue. ChrisA |

Re: Arithmetic with Boolean valuesOn 11/08/2012 23:30, John Ladasky wrote:
> I have gotten used to switching back and forth between Boolean algebra and numerical values. Python generally makes this quite easy. I just found a case that surprises me. > > Here is what I want to accomplish: I want to process a list. If the length of the list L is odd, I want to process it once. If len(L) is even, I want to process it twice. I thought I would set up a loop as follows: > > for x in range(1 + not(len(L) % 2)): > # Do stuff > > This provoked a SyntaxError. I investigated this further with my interpreter (ipython). > > In [1]: L = range(5) > > In [2]: L > Out[2]: [0, 1, 2, 3, 4] > > In [3]: len(L) > Out[3]: 5 > > In [4]: len(L) % 2 > Out[4]: 1 > > In [5]: not(1) > Out[5]: False > > In [6]: not(len(L) % 2) > Out[6]: False > > In [7]: 1 + not(len(L) % 2) > ------------------------------------------------------------ > File "<ipython console>", line 1 > 1 + not(len(L) % 2) > ^ > SyntaxError: invalid syntax > > So as you can see, every thing is working fine until I attempt to add 1 and False. However: > > In [8]: 0 == False > Out[8]: True > > In [9]: 1 == True > Out[9]: True > > So, 0 and False do pass an equivalency test, as do 1 and True. Furthermore: > > In [10]: 1 + (len(L) % 2 == 0) > Out[10]: 1 > > Why is using a logical "not" function, as shown in [7], returning a different result than the test for equivalency as shown in [10]? > > Of course I'm just going to use [10] in my program, but I'd like to understand the reason that I'm getting that SyntaxError. I've been reading Python style guides, and at least one of them states a preference for using the "not" syntax over the "== 0" syntax. > > I'm using Python 2.7, in case it matters. > I think the problem is that "not" isn't a function as such - it doesn't require parentheses, for example. The relevant syntax rules are: a_expr ::= m_expr | a_expr "+" m_expr | a_expr "-" m_expr m_expr ::= u_expr | m_expr "*" u_expr | m_expr "//" u_expr | m_expr "/" u_expr | m_expr "%" u_expr u_expr ::= power | "-" u_expr | "+" u_expr | "~" u_expr power ::= primary ["**" u_expr] primary ::= atom | attributeref | subscription | slicing | call atom ::= identifier | literal | enclosure enclosure ::= parenth_form | list_display | dict_display | set_display | generator_expression | yield_atom call ::= primary "(" [argument_list [","] | comprehension] ")" In order for your code to work I think we would need to have something like this: primary ::= atom | attributeref | subscription | slicing | call | not_expr not_expr ::= "not" parenth_form |

Re: Arithmetic with Boolean valuesJohn Ladasky <john_ladasky@sbcglobal.net> writes:
> I have gotten used to switching back and forth between Boolean algebra > and numerical values. Python generally makes this quite easy. Generally ugly though, at least to my tastes. "Explicit is better than implicit" as the saying goes. > If the length of the list L is odd, I want to process it once. If > len(L) is even, I want to process it twice.... > for x in range(1 + not(len(L) % 2)): If you really have to do something like that, I'd say for x in range(1 + (len(L) & 1)): or for x in range(2 - len(L) % 2): are simpler and avoid those bogus bool conversions. I'd prefer to just say the intention: for x in range(1 if len(L)%2==1 else 2): > This provoked a SyntaxError. "not" is a syntactic keyword and "1 + not" is syntactically invalid. You could write "1 + (not ...)" as you discovered, but really, it's hackish. |

Re: Arithmetic with Boolean valuesOn Sat, 11 Aug 2012 17:54:40 -0700, Paul Rubin wrote:
> John Ladasky <john_ladasky@sbcglobal.net> writes: [...] >> If the length of the list L is odd, I want to process it once. If >> len(L) is even, I want to process it twice.... >> for x in range(1 + not(len(L) % 2)): > > If you really have to do something like that, I'd say > > for x in range(1 + (len(L) & 1)): [snip] I'd simplify it even more: for x in (0,) if len(L)%2 else (0, 1): ... which is even more explicit and simpler to read even though it is longer. -- Steven |

Re: Arithmetic with Boolean valuesIn article <502791ea$0$29978$c3e8da3$5496439d@news.astraweb.c om>,
Steven D'Aprano <steve+comp.lang.python@pearwood.info> wrote: > for x in (0,) if len(L)%2 else (0, 1): > ... > > which is even more explicit and simpler to read even though it is longer. Ugh. do_stuff() if len(L) % 2 == 0: do_stuff() # reprocess even-length list Sure, it's 3 lines instead of one, but dead-obvious what the intention is. I might even go for: if len(L) % 2: do_stuff() else: do_stuff() do_stuff() There's two problems with all the looping suggestions people have given. One is that the computation of whether you need to do it once or twice is messy. But, but bigger issue is you're trying to warp what's fundamentally a boolean value into a looping construct. That's a cognitive mismatch. |

Re: Arithmetic with Boolean valuesOn Sun, 12 Aug 2012 07:40:30 -0400, Roy Smith wrote:
> In article <502791ea$0$29978$c3e8da3$5496439d@news.astraweb.c om>, > Steven D'Aprano <steve+comp.lang.python@pearwood.info> wrote: > >> for x in (0,) if len(L)%2 else (0, 1): >> ... >> >> which is even more explicit and simpler to read even though it is >> longer. > > Ugh. > > do_stuff() > if len(L) % 2 == 0: > do_stuff() # reprocess even-length list > > Sure, it's 3 lines instead of one, but dead-obvious what the intention > is. Well, sure, for that specific case that would work too. Using a for-loop to do something once is a little icky. But only a little. Also, it scales to situations like "repeat 37 times when even, or 82 times when odd" (or any other values). > There's two problems with all the looping suggestions people have given. > One is that the computation of whether you need to do it once or twice > is messy. But, but bigger issue is you're trying to warp what's > fundamentally a boolean value into a looping construct. That's a > cognitive mismatch. Really? You've never used a while loop? while not finished: do_something() There's nothing wrong with having a for-loop which iterates over a computed set of values: if len(L)%2: items = range(len(L)//2 + 1) else: items = range(len(L)//2) for x in items: ... which can be simplified to: for x in range(len(L)//2 + len(L)%2): ... -- Steven |

All times are GMT. The time now is 01:23 PM. |

Powered by vBulletin®. Copyright ©2000 - 2014, vBulletin Solutions, Inc.

SEO by vBSEO ©2010, Crawlability, Inc.