returning True, False or None

Discussion in 'Python' started by Jeremy Bowers, Feb 4, 2005.

  1. On Fri, 04 Feb 2005 10:48:44 -0700, Steven Bethard wrote:

    > I have lists containing values that are all either True, False or None,
    > e.g.:
    >
    > [True, None, None, False]
    > [None, False, False, None ]
    > [False, True, True, True ]
    > etc.
    >
    > For a given list:
    > * If all values are None, the function should return None.
    > * If at least one value is True, the function should return True.
    > * Otherwise, the function should return False.
    >
    > Right now, my code looks like:
    >
    > if True in lst:
    > return True
    > elif False in lst:
    > return False
    > else:
    > return None


    Yes, I see the smell, you are searching the list multiple times. You
    could bail out when you can:

    seenFalse = False
    for item in list:
    if item: return True
    if item is False: seenFalse = True
    if seenFalse:
    return False
    return None

    But I'd submit that if four item lists are your common case, that your
    original code is significantly easier to understand what it is doing. This
    can be alleviated with an appropriate comment on the chunk of code I gave
    you, though.
     
    Jeremy Bowers, Feb 4, 2005
    #1
    1. Advertising

  2. On Fri, 04 Feb 2005 16:44:48 -0500, Daniel Bickett wrote:
    > [ False , False , True , None ]
    >
    > False would be returned upon inspection of the first index, even
    > though True was in fact in the list. The same is true of the code of
    > Jeremy Bowers, Steve Juranich, and Jeff Shannon. As for Raymond
    > Hettinger, I can't even be sure ;)


    Nope. To recall, my code was:

    seenFalse = False
    for item in list:
    if item: return True
    if item is False: seenFalse = True
    if seenFalse:
    return False
    return None

    So, turning that into a real function and not a sketch:

    Python 2.3.4 (#1, Jan 25 2005, 21:29:33)
    [GCC 3.4.3 (Gentoo Linux 3.4.3, ssp-3.4.3-0, pie-8.7.6.6)] on linux2
    Type "help", "copyright", "credits" or "license" for more information.
    >>> def thingy(l):

    .... seenFalse = False
    .... for item in l:
    .... if item: return True
    .... if item is False: seenFalse = True
    .... if seenFalse:
    .... return False
    .... return None
    ....
    >>> thingy([ False , False , True , None ])

    True
    >>>


    The defense rests, your honor. :)

    (I like the later use of "returnValue" and the reduce solution was cute
    and quite educational (very appropriate here). I deliberately eschewed
    fanciness, though.)
     
    Jeremy Bowers, Feb 4, 2005
    #2
    1. Advertising

  3. I have lists containing values that are all either True, False or None,
    e.g.:

    [True, None, None, False]
    [None, False, False, None ]
    [False, True, True, True ]
    etc.

    For a given list:
    * If all values are None, the function should return None.
    * If at least one value is True, the function should return True.
    * Otherwise, the function should return False.

    Right now, my code looks like:

    if True in lst:
    return True
    elif False in lst:
    return False
    else:
    return None

    This has a light code smell for me though -- can anyone see a simpler
    way of writing this?

    STeVe
     
    Steven Bethard, Feb 4, 2005
    #3
  4. Steven Bethard <> wrote:

    > I have lists containing values that are all either True, False or None,
    > e.g.:
    >
    > [True, None, None, False]
    > [None, False, False, None ]
    > [False, True, True, True ]
    > etc.
    >
    > For a given list:
    > * If all values are None, the function should return None.
    > * If at least one value is True, the function should return True.
    > * Otherwise, the function should return False.
    >
    > Right now, my code looks like:
    >
    > if True in lst:
    > return True
    > elif False in lst:
    > return False
    > else:
    > return None
    >
    > This has a light code smell for me though -- can anyone see a simpler
    > way of writing this?


    What about...:

    for val in lst:
    if val is not None:
    return val
    return None

    or the somewhat fancy/clever:

    for val in (x for x in lst if x is not None):
    return val
    return None


    Alex
     
    Alex Martelli, Feb 4, 2005
    #4
  5. "Steven Bethard"
    > For a given list:
    > * If all values are None, the function should return None.
    > * If at least one value is True, the function should return True.
    > * Otherwise, the function should return False.

    . . .
    > Right now, my code looks like:
    >
    > if True in lst:
    > return True
    > elif False in lst:
    > return False
    > else:
    > return None
    >
    > This has a light code smell for me though -- can anyone see a simpler
    > way of writing this?



    return max(lst)


    Raymond Hettinger
     
    Raymond Hettinger, Feb 4, 2005
    #5
  6. Jeremy Bowers

    Steve Holden Guest

    Steven Bethard wrote:

    > I have lists containing values that are all either True, False or None,
    > e.g.:
    >
    > [True, None, None, False]
    > [None, False, False, None ]
    > [False, True, True, True ]
    > etc.
    >
    > For a given list:
    > * If all values are None, the function should return None.
    > * If at least one value is True, the function should return True.
    > * Otherwise, the function should return False.
    >
    > Right now, my code looks like:
    >
    > if True in lst:
    > return True
    > elif False in lst:
    > return False
    > else:
    > return None
    >
    > This has a light code smell for me though -- can anyone see a simpler
    > way of writing this?
    >
    > STeVe


    That code looks like a pretty solid implementation of the spec to me.
    There isn't a strict need for the last else, of course, which may be the
    smell you detect.

    If you wanted to get clever you could write something like

    for i in True, False:
    if i in lst:
    return i
    return False

    but frankly I think that's more obscure, and saves you pretty much nothing.

    regards
    Steve
    --
    Meet the Python developers and your c.l.py favorites March 23-25
    Come to PyCon DC 2005 http://www.pycon.org/
    Steve Holden http://www.holdenweb.com/
     
    Steve Holden, Feb 4, 2005
    #6
  7. Steven Bethard wrote:
    > I have lists containing values that are all either True, False or None,
    > e.g.:
    >
    > [True, None, None, False]
    > [None, False, False, None ]
    > [False, True, True, True ]
    > etc.
    >
    > For a given list:
    > * If all values are None, the function should return None.
    > * If at least one value is True, the function should return True.
    > * Otherwise, the function should return False.
    >
    > Right now, my code looks like:
    >
    > if True in lst:
    > return True
    > elif False in lst:
    > return False
    > else:
    > return None
    >
    > This has a light code smell for me though -- can anyone see a simpler
    > way of writing this?
    >
    > STeVe


    max(lst) ;-)

    Michael
     
    Michael Spencer, Feb 4, 2005
    #7
  8. Raymond Hettinger wrote:
    > "Steven Bethard"
    >
    >>For a given list:
    >>* If all values are None, the function should return None.
    >>* If at least one value is True, the function should return True.
    >>* Otherwise, the function should return False.

    >
    > . . .
    >
    >>Right now, my code looks like:
    >>
    >> if True in lst:
    >> return True
    >> elif False in lst:
    >> return False
    >> else:
    >> return None
    >>
    >>This has a light code smell for me though -- can anyone see a simpler
    >>way of writing this?

    >
    >
    > return max(lst)


    Very clever! Thanks!

    Steve
     
    Steven Bethard, Feb 4, 2005
    #8
  9. Steven Bethard wrote:
    > I have lists containing values that are all either True, False or
    > None, e.g.:
    >
    > [True, None, None, False]
    > [None, False, False, None ]
    > [False, True, True, True ]
    > etc.
    >
    > For a given list:
    > * If all values are None, the function should return None.
    > * If at least one value is True, the function should return True.
    > * Otherwise, the function should return False.


    Try:

    >>> max(lst)


    Mick.
     
    Mick Krippendorf, Feb 4, 2005
    #9
  10. Alex Martelli said unto the world upon 2005-02-04 13:02:
    > Steven Bethard <> wrote:
    >
    >
    >>I have lists containing values that are all either True, False or None,
    >>e.g.:
    >>
    >> [True, None, None, False]
    >> [None, False, False, None ]
    >> [False, True, True, True ]
    >> etc.
    >>
    >>For a given list:
    >>* If all values are None, the function should return None.
    >>* If at least one value is True, the function should return True.
    >>* Otherwise, the function should return False.
    >>
    >>Right now, my code looks like:


    <SNIP OP's code>

    >>This has a light code smell for me though -- can anyone see a simpler
    >>way of writing this?

    >
    >
    > What about...:
    >
    > for val in lst:
    > if val is not None:
    > return val
    > return None
    >
    > or the somewhat fancy/clever:
    >
    > for val in (x for x in lst if x is not None):
    > return val
    > return None
    >
    >
    > Alex


    These don't do what the OP desired.

    ..>>> test_case = [False, True, True, True ]
    ..>>> def alexs_funct(lst):
    .. for val in lst:
    .. if val is not None:
    .. return val
    .. return None

    >>> alexs_funct(test_case)

    False

    But, by the 'spec', it ought return True.

    Best,

    Brian vdB
    A mere newbie, quite pleased with himself for finding a problem with
    'bot code -- next scheduled to occur mid 2011 :)
     
    Brian van den Broek, Feb 4, 2005
    #10
  11. Steven Bethard wrote:

    >> return max(lst)

    >
    > Very clever! Thanks!


    too clever. boolean > None isn't guaranteed by the language specification:

    http://docs.python.org/ref/comparisons.html

    "... objects of different types always compare unequal, and are ordered consistently
    but arbitrarily. /.../ In the future, the comparison rules for objects of different types are
    likely to change. ..."

    </F>
     
    Fredrik Lundh, Feb 4, 2005
    #11
  12. Jeremy Bowers

    Peter Otten Guest

    Steven Bethard wrote:

    > I have lists containing values that are all either True, False or None,
    > e.g.:
    >
    > [True, None, None, False]
    > [None, False, False, None ]
    > [False, True, True, True ]
    > etc.
    >
    > For a given list:
    > * If all values are None, the function should return None.
    > * If at least one value is True, the function should return True.
    > * Otherwise, the function should return False.
    >
    > Right now, my code looks like:
    >
    > if True in lst:
    > return True
    > elif False in lst:
    > return False
    > else:
    > return None
    >
    > This has a light code smell for me though -- can anyone see a simpler
    > way of writing this?


    An attempt to short-circuit if possible:

    def tristate(iterable):
    it = iter(iterable)
    for item in it:
    if item is not None:
    return item or True in it

    Not as elegant as max(), but makes me wonder whether a max() that accepts an
    additional upper_bound argument and returns upper_bound as soon as it
    encounters a value >= upper_bound would be worth the effort.

    Peter
     
    Peter Otten, Feb 4, 2005
    #12
  13. Fredrik Lundh wrote:
    > Steven Bethard wrote:
    >> Raymond Hettinger wrote:
    >>>
    >>> return max(lst)

    >>
    >> Very clever! Thanks!

    >
    > too clever. boolean > None isn't guaranteed by the language specification:


    Yup. I thought about mentioning that for anyone who wasn't involved in
    the previous thread discussing this behavior, but I was too lazy. ;)
    Thanks for pointing it out again.

    This implementation detail was added in Python 2.1a1, with the following
    note[1]:

    "The outcome of comparing non-numeric objects of different types is
    not defined by the language, other than that it's arbitrary but
    consistent (see the Reference Manual). An implementation detail changed
    in 2.1a1 such that None now compares less than any other object. Code
    relying on this new behavior (like code that relied on the previous
    behavior) does so at its own risk."

    Steve

    [1] http://www.python.org/2.1/NEWS.txt
     
    Steven Bethard, Feb 4, 2005
    #13
  14. Jeremy Bowers

    Jeff Shannon Guest

    Jeremy Bowers wrote:

    > On Fri, 04 Feb 2005 10:48:44 -0700, Steven Bethard wrote:
    >
    >>For a given list:
    >>* If all values are None, the function should return None.
    >>* If at least one value is True, the function should return True.
    >>* Otherwise, the function should return False.

    >
    > Yes, I see the smell, you are searching the list multiple times. You
    > could bail out when you can:
    >
    > seenFalse = False
    > for item in list:
    > if item: return True
    > if item is False: seenFalse = True
    > if seenFalse:
    > return False
    > return None


    I'd modify this approach slightly...

    def tfn(lst):
    answer = None
    for item in lst:
    if item is True: return True
    if item is False: answer = False
    return answer

    But yeah, the original, straightforward way is probably enough clearer
    that I wouldn't bother with anything else unless lists might be long
    enough for performance to matter.

    Jeff Shannon
    Technician/Programmer
    Credit International
     
    Jeff Shannon, Feb 4, 2005
    #14
  15. "Steven Bethard"
    > For a given list:
    > * If all values are None, the function should return None.
    > * If at least one value is True, the function should return True.
    > * Otherwise, the function should return False.


    One more approach, just for grins:

    s = set(lst)
    return True in s or s == set([None]) and None


    Raymond Hettinger
     
    Raymond Hettinger, Feb 4, 2005
    #15
  16. I'm seeing a consistent problem in most of these approaches.
    Verbalized, the logic of the OP's original code reads as such:

    If True is in the list *at all*, return True.
    Otherwise, if False is in the list *at all*, return False.
    Otherwise, return None.

    So if we used Alex Martelli's code:

    > for val in lst:
    > if val is not None:
    > return val
    > return None


    and the list was:

    [ False , False , True , None ]

    False would be returned upon inspection of the first index, even
    though True was in fact in the list. The same is true of the code of
    Jeremy Bowers, Steve Juranich, and Jeff Shannon. As for Raymond
    Hettinger, I can't even be sure ;)

    The original OP's code, on the other hand, inadvertently searches
    through the list twice where once would have sufficed, causing a
    needless performance pitfall. The following applies the OP's initial
    logic while only iterating once:

    >>> def boolhunt( items ):

    falseExists = False
    for item in items:
    if item is True:
    return True
    elif item is False and not falseExists:
    falseExists = True
    if falseExists:
    return False
    >>> l1 = [ True , None , None , False ]
    >>> l2 = [ None , False , False , None ]
    >>> l3 = [ False , True , True , True ]
    >>> boolhunt( l1 )

    True
    >>> boolhunt( l2 )

    False
    >>> boolhunt( l3 )

    True

    It isn't elegant or clever, but it gets the job done :)

    --
    Daniel Bickett
    dbickett at gmail.com
    http://heureusement.org/
     
    Daniel Bickett, Feb 4, 2005
    #16
  17. Jeremy Bowers wrote:
    > The defense rests, your honor. :)


    I stand corrected :) My apologies.

    --
    Daniel Bickett
    dbickett at gmail.com
    http://heureusement.org/
     
    Daniel Bickett, Feb 4, 2005
    #17
  18. Fredrik Lundh wrote:
    > Steven Bethard wrote:
    >> Raymond Hettinger wrote:
    >>>
    >>> return max(lst)

    >>
    >> Very clever! Thanks!

    >
    > too clever. boolean > None isn't guaranteed by the language
    > specification:
    >
    > http://docs.python.org/ref/comparisons.html
    >
    > "... objects of different types always compare unequal, and are
    > ordered consistently but arbitrarily. /.../ In the future, the
    > comparison rules for objects of different types are likely to
    > change. ..."


    Then maybe like this:

    >>> def max_of_two_with_None_less_than_any_other_object(e1, e2):

    ... if e1 == None:
    ... return e2
    ... elif e2 == None:
    ... return e1
    ... else:
    ... return max(e1, e2)

    >>> reduce(max_of_two_with_None_less_than_any_other_object, lst)


    Mick.
     
    Mick Krippendorf, Feb 4, 2005
    #18
  19. Jeremy Bowers

    Jeff Shannon Guest

    Jeremy Bowers wrote:

    > On Fri, 04 Feb 2005 16:44:48 -0500, Daniel Bickett wrote:
    >
    >>[ False , False , True , None ]
    >>
    >>False would be returned upon inspection of the first index, even
    >>though True was in fact in the list. The same is true of the code of
    >>Jeremy Bowers, Steve Juranich, and Jeff Shannon. As for Raymond
    >>Hettinger, I can't even be sure ;)

    >
    > Nope.


    Indeed. Similarly for mine, which was really just a slight transform
    of Jeremy's (setting a return variable directly, instead of setting a
    flag that's later used to decide what to return):

    >>> def tfn(lst):

    .... answer = None
    .... for item in lst:
    .... if item is True: return True
    .... if item is False: answer = False
    .... return answer
    ....
    >>> list = [False, False, True, None]
    >>> tfn(list)

    1
    >>> list = [None, False, False, None]
    >>> tfn(list)

    0
    >>> list = [None, None, None, None]
    >>> print tfn(list)

    None
    >>> >>>


    The noted logical flaw *has* been present in a number of proposed
    solutions, however.

    The key point to note is that one *must* examine the entire list
    *unless* you find a True; short-circuiting on False means that you may
    miss a later True.

    Jeff Shannon
    Technician/Programmer
    Credit International
     
    Jeff Shannon, Feb 4, 2005
    #19
  20. Daniel Bickett wrote:
    >
    > >>> def boolhunt( items ):

    > ... falseExists = False
    > ... for item in items:
    > ... if item is True:
    > ... return True
    > ... elif item is False and not falseExists:
    > ... falseExists = True
    > ... if falseExists:
    > ... return False




    Or even shorter:

    >>> def boolhunt(items):

    ... result = None
    ... for item in items:
    ... if item:
    ... return True
    ... elif result is None and item is False:
    ... result = False
    ... return result


    Or like the Melmacians would do it:

    >>> def boolgen(items):

    ... result = None
    ... for item in items:
    ... if result:
    ... raise StopIteration
    ... elif item is not None:
    ... result = item
    ... yield result

    >>> [item for item in boolgen(a_list)][-1]



    Mick.
     
    Mick Krippendorf, Feb 5, 2005
    #20
    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. André
    Replies:
    3
    Views:
    1,618
  2. bdb112
    Replies:
    45
    Views:
    1,373
    jazbees
    Apr 29, 2009
  3. length power
    Replies:
    2
    Views:
    104
    Rustom Mody
    Apr 10, 2014
  4. Skip Montanaro
    Replies:
    0
    Views:
    71
    Skip Montanaro
    Apr 10, 2014
  5. Johannes Schneider

    Re: why i have the output of [None, None, None]

    Johannes Schneider, Apr 10, 2014, in forum: Python
    Replies:
    0
    Views:
    61
    Johannes Schneider
    Apr 10, 2014
Loading...

Share This Page