4

I am trying to return a boolean in a function like this:

return mylist and any(condition(x) for x in mylist)

The behavior should be to return True if the list is empty or if any element in it meets the condition. I am using the first operand as a shortcircuit since any would return True if the list was empty, which is not what I am after.

I would expect [] and boolval to return False since the list is empty, but to my surprise it returns [] whether boolval is True or False. I would expect the first operand to be automatically evaluated as a boolean since it is involved in a comparison operation, and not whatever is happening.

I am not really asking how to solve my problem, which is easily done by an explicit type conversion: bool(mylist), but rather asking what is happening and why.

edit: when I ask "why" this is happening I am not looking for the "facts" only, as they are already explained in the linked duplicate question, but also the reasons behind the implementation of this behavior.

dabadaba
  • 9,064
  • 21
  • 85
  • 155

3 Answers3

6

The and and or operators do not return True/False. They return the last thing evaluated (that's the case in other dynamic languages too, eg. javascript).

The official documentation describes that

  • for and, the first falsy value, or the last operand
  • for or, the first truthy value, or the last operand

That's by design, so you can create expressions like return username or 'guest'. So, if you want guarantee that a boolean value is returned, you have to

return bool(x or y)

instead of

return x or y
blue_note
  • 27,712
  • 9
  • 72
  • 90
  • How did I not know this? I am used to `x or y`, I use it all the time for assignments when `x` is falsy, but I did not know it what a thing for `and` too. Can you link to the docs where they cover this matter and especially the reasoning of implementing this behavior? – dabadaba Oct 02 '18 at 09:27
  • #@dabadaba: edited. The reasoning for design choices however is not provided in any language's reference that I know of. It seems to be something along the lines of "give me the first non-empty list" for `and`, or "set a default value" for `or`. – blue_note Oct 02 '18 at 09:34
  • This is another bit of documentation that is a bit more explicit. Or rather it gives a table of the operators with a short explanation of their results. Just before it gives a detailed explanation of how an object is considered true or false. https://docs.python.org/3/library/stdtypes.html#boolean-operations-and-or-not – Dunes Oct 02 '18 at 09:37
1

Because as khelwood said:

x and y gives x if x is falsey, otherwise it gives y.

That's the point, (and is not or :-)), so still best is:

return all([my_list,any(condition(x) for x in my_list)])
U13-Forward
  • 69,221
  • 14
  • 89
  • 114
0

This has to do with how python evaluate the expression.

An empty list is considered as false by python, that means that the code after 'and' will not be executed, as this will not change the result.

Python does not need to convert the empty list into bool as it is not compared to anything, and just return it as empty list.

This shouldn't change anything for you, if you test the returned value of the function, it will be evaluate the same way as if the function did return False.

tagette
  • 68
  • 4