0

I was testing the all() and any() functions to make sure I understood how they operate. Turns out I do not understand them. Here is my test code:

v1=[True, False, True] # unexpected 2
v2=[True]              # wai
v3=[]                  # unexpected 2
v4=[False]             # wai
v5=[False,False]       # wai
v6=[False,False, True] # unexpected 2
v7=[False]*4           # wai
v8=[float('nan'),False]# unexpected 1, but I think this is because any() considers "truthy" values. Given this, 2 is unexpected.
v9=['f','t']           # wai, given "truthy" values. Would like this to return False.
v10=['random_string']  # same as above
vlist=[v1,v2,v3,v4,v5,v6,v7,v8,v9,v10]

for v in vlist:
    print('any true:',any(v)==True,'| not all false:',not(all(v)==False),'(',v,')')

Returns:

any true: True | not all false: False ( [True, False, True] )
any true: True | not all false: True ( [True] )
any true: False | not all false: True ( [] )
any true: False | not all false: False ( [False] )
any true: False | not all false: False ( [False, False] )
any true: True | not all false: False ( [False, False, True] )
any true: False | not all false: False ( [False, False, False, False] )
any true: True | not all false: False ( [nan, False] )
any true: True | not all false: True ( ['f', 't'] )
any true: True | not all false: True ( ['random_string'] )

Where I've coded the output to display the logical summary of the statement (ex: any true), followed by the evaluated value. This is done for both statements, and then the parenthetical at the end shows the list evaluated.

Most of my surprises come from the not all() combination. But I was also expecting non-true values (ex: float('nan') or 'random_string') to be false. Looking at the documentation I see that this is not the case, but I would like to know how to make this an option.

I attempted to code tests for the logical statements: "are any True?" and "not: are all False?". If I'm not mistaken, these should be logically identical.

Some more detailed explanations for my surprises. I refer to the "inside" statement as all(v)==False and the negation of this being the outside statement:

  • v1=[True, False, True] - For the inside statement, I consider whether all elements are False. This is clearly not the case, so I expect the statement to be false. The outside not negates this, so the result of this should be True.
  • v3=[] - The set is empty. Thus all elements are false is True, and not this should be false.
  • v6=[False,False, True] - It's clear that there are some True elements, so the inside statement is False. Not this, means it should be True.
  • v8=[float('nan'),False] - This one is a puzzle for me. I'd like 'nan' to read as False (only accept True values), but looking at the documentation this is not how it works. Given this piece of information, it is unexpected that the second statement reads False, since 'nan' is a "truthy" value. So all elements are False is a false statement, and negated I'd expect the output to be True.
  • v9 and v10 Are working as expected once I learned about the "truthy" values. However, I'd like them to read False under both circumstances (considering only 1 or True as a True value, others as False). Of particular concern to my current project is reading 'nan','NaN',etc. as False.
amquack
  • 837
  • 10
  • 24
  • 2
    `not(all(v)==False)` does not mean "not all false". Similarly `any(v) == True` is redundant, it means just `any(v)`. – juanpa.arrivillaga Jan 29 '21 at 16:53
  • 1
    "I'd like 'nan' to read as False " well, I'd like a lot of things, but `nan` is not falsy, the only falsy `float` is `0.0`. – juanpa.arrivillaga Jan 29 '21 at 16:54
  • "However, I'd like them to read False under both circumstances (considering only 1 or True as a True value, others as False)" Again, then you *have to convert the values*. – juanpa.arrivillaga Jan 29 '21 at 16:55
  • @juanpa.arrivillaga I see - how do I check "not all false"? – amquack Jan 29 '21 at 16:55
  • @dawg this is very helpful for eliminating the truthy/falsy confusion - but does not address my misunderstanding of how to ask the logic question (ex: v1,v3) – amquack Jan 29 '21 at 16:59
  • 1
    Well, the wordy way is `not all(not x for x in v)` but really, you just want `any(v)` (i.e. any true, at least one true is the same as not all false) – juanpa.arrivillaga Jan 29 '21 at 17:00
  • 1
    Sounds like you need to study [de Morgan's Laws](https://en.wikipedia.org/wiki/De_Morgan%27s_laws) – Barmar Jan 29 '21 at 17:05
  • 1
    Yes, you really need to grok de Morgan's laws. But you are treating python like natural language english, `not(all(v)==False)` does not distribute `== False` across the items of `v` and *then* uses `all`, rather, it uses `all` first, then checks if it is false, which basically just makes `not (....)` a double negative. `not (all(v) == False)` is just `all(v)` – juanpa.arrivillaga Jan 29 '21 at 17:08
  • Also, `== False` and `== True` is almost never what you actually want, because of "truthiness". – juanpa.arrivillaga Jan 29 '21 at 17:09
  • 1
    I have given links for what I think are the interesting points of your confusion 1) `nan` has interesting properties. Among them is all comparisons, including to itself, are `False` and it is a 'truthy' object; 2) `all` and `any` on empty lists and 3) what exactly is truthy and falsy? All your other issues are basic logic. – dawg Jan 29 '21 at 17:32
  • I don't see an error in my logic (but would love it if you showed it to me!), it seems to me it was a coding issue (particularly around distributing the `==False`). That said, your comments have led me to be able to code what I wanted: `def notruthy(v): return [True if x==True else False for x in v]` and `print('any true:',any(notruthy(v)),'| not all false:',not all(not x for x in notruthy(v)),'(',v,')')`, as well as argue that it's probably not what I should want to code. – amquack Jan 29 '21 at 17:39
  • The logic issues are covered [here](https://docs.python.org/3/library/stdtypes.html#truth-value-testing) and are mostly about what truthy things are in Python. A string with something, even `'0'` is a truthy thing. – dawg Jan 29 '21 at 17:56

0 Answers0