Groups | Search | Server Info | Keyboard shortcuts | Login | Register [http] [https] [nntp] [nntps]


Groups > comp.lang.python > #101330 > unrolled thread

True/False value testing

Started by"ast" <nomail@invalid.com>
First post2016-01-07 11:36 +0100
Last post2016-01-07 12:11 +0100
Articles 8 — 4 participants

Back to article view | Back to comp.lang.python


Contents

  True/False value testing "ast" <nomail@invalid.com> - 2016-01-07 11:36 +0100
    Re: True/False value testing Peter Otten <__peter__@web.de> - 2016-01-07 11:48 +0100
    Re: True/False value testing Chris Angelico <rosuav@gmail.com> - 2016-01-07 21:49 +1100
      Re: True/False value testing Marko Rauhamaa <marko@pacujo.net> - 2016-01-07 13:19 +0200
        Re: True/False value testing Chris Angelico <rosuav@gmail.com> - 2016-01-07 22:50 +1100
          Re: True/False value testing Marko Rauhamaa <marko@pacujo.net> - 2016-01-07 14:07 +0200
            Re: True/False value testing Chris Angelico <rosuav@gmail.com> - 2016-01-07 23:38 +1100
    Re: True/False value testing "ast" <nomail@invalid.com> - 2016-01-07 12:11 +0100

#101330 — True/False value testing

From"ast" <nomail@invalid.com>
Date2016-01-07 11:36 +0100
SubjectTrue/False value testing
Message-ID<568e3fb4$0$659$426a74cc@news.free.fr>
Hello

For integer, 0 is considered False and any other value True

>>> A=0
>>> A==False
True
>>> A==True
False
>>> A=1
>>> A==False
False
>>> A==True
True

It works fine

For string, "" is considered False and any other value True,
but it doesn't work

>>> A = ""
>>> A==False
False
>>> A==True
False
>>> A = 'Z'
>>> A==False
False
>>> A==True
False


What happens ???

thx

[toc] | [next] | [standalone]


#101331

FromPeter Otten <__peter__@web.de>
Date2016-01-07 11:48 +0100
Message-ID<mailman.42.1452163742.2305.python-list@python.org>
In reply to#101330
ast wrote:

> Hello
> 
> For integer, 0 is considered False and any other value True
> 
>>>> A=0
>>>> A==False
> True
>>>> A==True
> False
>>>> A=1
>>>> A==False
> False
>>>> A==True
> True
> 
> It works fine

But not the way you think:

>>> 0 == False
True
>>> 1 == True
True
>>> 2 == True
False
>>> 2 == False
False

0 equals False, 1 equals True, and any other integer equals neither, but 
"is true in a boolean context", i. e.

>>> if 42: print("42 considered true")
... 
42 considered true

> For string, "" is considered False and any other value True,
> but it doesn't work

In a similar way there is no string that equals True or False, but
the empty string "" is considered false in a boolean context while all other 
strings are considered true:

>>> bool("")
False
>>> bool("whatever")
True

>>>> A = ""
>>>> A==False
> False
>>>> A==True
> False
>>>> A = 'Z'
>>>> A==False
> False
>>>> A==True
> False
> 
> 
> What happens ???
> 
> thx

[toc] | [prev] | [next] | [standalone]


#101332

FromChris Angelico <rosuav@gmail.com>
Date2016-01-07 21:49 +1100
Message-ID<mailman.43.1452163794.2305.python-list@python.org>
In reply to#101330
On Thu, Jan 7, 2016 at 9:36 PM, ast <nomail@invalid.com> wrote:
> Hello
>
> For integer, 0 is considered False and any other value True
>
>>>> A=0
>>>> A==False
>
> True
>>>>
>>>> A==True
>
> False
>>>>
>>>> A=1
>>>> A==False
>
> False
>>>>
>>>> A==True
>
> True
>
> It works fine
>
> For string, "" is considered False and any other value True,
> but it doesn't work
>
>>>> A = ""
>>>> A==False
>
> False
>>>>
>>>> A==True
>
> False
>>>>
>>>> A = 'Z'
>>>> A==False
>
> False
>>>>
>>>> A==True
>
> False
>
>
> What happens ???
>
> thx

There's a difference between "is considered false" and "is equal to
False". In Python, most collections are considered false if they are
empty:

def truthiness(x):
    if x:
        print(repr(x) + " is true")
    else:
        print(repr(x) + " is false")

truthiness([])
truthiness([1,2,3])
truthiness("")
truthiness("hello")
truthiness(0)
truthiness(73)
truthiness({})
truthiness({1:2, 3:4})

However, none of these will compare *equal* to the Boolean values True
and False, save for the integers 1 and 0. In fact, True is a special
form of the integer 1, and False is a special form of the integer 0;
they are considered to represent those numbers just as much as the
floating point values 1.0 and 0.0 do:

from decimal import Decimal
from fractions import Fraction
# Caveat, see footnote [1]
if Fraction(0, 1) == 0.0 == 0 == False == Decimal("0"):
    print("See? All representations of zero are equal")

Intuition tells you quite obviously that the integers 1 and 73 are not
equal, but both of them are very definitely truthy values. In the same
way, a non-empty list is truthy, but it's not equal to True.

Does that answer your question?

ChrisA

[1] In Python 2.7, Decimal("0") != Fraction(0, 1). I suspect this is a
bug, as it's been fixed in Python 3; both of them are equal to the
integer 0, but they're not equal to each other. So the order of checks
in that demo is actually significant.

[toc] | [prev] | [next] | [standalone]


#101334

FromMarko Rauhamaa <marko@pacujo.net>
Date2016-01-07 13:19 +0200
Message-ID<877fjl7i30.fsf@elektro.pacujo.net>
In reply to#101332
Chris Angelico <rosuav@gmail.com>:

> However, none of these will compare *equal* to the Boolean values True
> and False, save for the integers 1 and 0. In fact, True is a special
> form of the integer 1, and False is a special form of the integer 0;

Stirring the pot:

   >>> (2 < 3) is True
   True

but is that guaranteed?


Marko

[toc] | [prev] | [next] | [standalone]


#101335

FromChris Angelico <rosuav@gmail.com>
Date2016-01-07 22:50 +1100
Message-ID<mailman.44.1452167431.2305.python-list@python.org>
In reply to#101334
On Thu, Jan 7, 2016 at 10:19 PM, Marko Rauhamaa <marko@pacujo.net> wrote:
> Chris Angelico <rosuav@gmail.com>:
>
>> However, none of these will compare *equal* to the Boolean values True
>> and False, save for the integers 1 and 0. In fact, True is a special
>> form of the integer 1, and False is a special form of the integer 0;
>
> Stirring the pot:
>
>    >>> (2 < 3) is True
>    True
>
> but is that guaranteed?

Yes. When you do comparisons involving integers, the result is an
actual boolean value - not just a truthy value, but the exact value
True or False. Those values, being singletons (or a doubleton, or
whatever you want to call it), will always be the same objects, ergo
the "is True" part must always pass.

However, if arbitrary objects are thrown into the mix, the guarantee
doesn't hold. Here's one way of implementing a "sticky NaN" that
infects all operations:

class NaN:
    def __lt__(self, other): return self
    __gt__ = __ge__ = __le__ = __lt__
    def __eq__(self, other): return False
    def __ne__(self, other): return True
    def __new__(cls):
        if not hasattr(cls, "_inst"):
            cls._inst = super().__new__(cls)
        return cls._inst
    def __repr__(self): return "NaN"

NaN = NaN()


And it looks something like this:

>>> NaN < 1
NaN
>>> 1 < NaN
NaN
>>> NaN > 1
NaN
>>> 1 > NaN
NaN
>>> NaN == NaN
False

Similarly, numpy arrays overload operators to perform elementwise comparisons:

>>> import numpy
>>> numpy.array(range(10))
array([0, 1, 2, 3, 4, 5, 6, 7, 8, 9])
>>> _ < 5
array([ True,  True,  True,  True,  True, False, False, False, False,
False], dtype=bool)

But with integers, and with most other built-in types, the comparison
operators are indeed guaranteed to return either True or False.

ChrisA

[toc] | [prev] | [next] | [standalone]


#101336

FromMarko Rauhamaa <marko@pacujo.net>
Date2016-01-07 14:07 +0200
Message-ID<871t9t7fup.fsf@elektro.pacujo.net>
In reply to#101335
Chris Angelico <rosuav@gmail.com>:

>> Stirring the pot:
>>
>>    >>> (2 < 3) is True
>>    True
>>
>> but is that guaranteed?
>
> Yes. When you do comparisons involving integers, the result is an
> actual boolean value - not just a truthy value, but the exact value
> True or False.

I couldn't locate that bold statement in the language spec (see <URL:
https://docs.python.org/3/library/stdtypes.html#comparisons>).

However, I *could* find this statement:

   1. [or] is a short-circuit operator, so it only evaluates the second
      argument if the first one is False.

   2. [and] is a short-circuit operator, so it only evaluates the second
      argument if the first one is True.

   <URL: https://docs.python.org/3/library/stdtypes.html#boolean-op
   erations-and-or-not>

The wording is very unfortunate (both the use of the word "is" and the
explicit references to the builtin constants False and True).


Marko

[toc] | [prev] | [next] | [standalone]


#101337

FromChris Angelico <rosuav@gmail.com>
Date2016-01-07 23:38 +1100
Message-ID<mailman.45.1452170304.2305.python-list@python.org>
In reply to#101336
On Thu, Jan 7, 2016 at 11:07 PM, Marko Rauhamaa <marko@pacujo.net> wrote:
> However, I *could* find this statement:
>
>    1. [or] is a short-circuit operator, so it only evaluates the second
>       argument if the first one is False.
>
>    2. [and] is a short-circuit operator, so it only evaluates the second
>       argument if the first one is True.
>
>    <URL: https://docs.python.org/3/library/stdtypes.html#boolean-op
>    erations-and-or-not>
>
> The wording is very unfortunate (both the use of the word "is" and the
> explicit references to the builtin constants False and True).

Actually, that's a good point. I would call that a docs error.

The definition of the comparison operators is, more or less:

1) Call a.__lt__(b). If it doesn't return NotImplemented, that's the value.
2) Call b.__gt__(a). If it doesn't return NotImplemented, that's the value.
3) Raise TypeError.

Massively simplified; steps 1 and 2 get switched around if b is a
subclass of a, and there's stuff about slots, and so on. But that's
basically it. The function is allowed to return anything it likes. The
built-in types generally return instances of bool, but custom classes
are free to generalize (as numpy has done to great effect).

ChrisA

[toc] | [prev] | [next] | [standalone]


#101333

From"ast" <nomail@invalid.com>
Date2016-01-07 12:11 +0100
Message-ID<568e47db$0$19774$426a74cc@news.free.fr>
In reply to#101330
"ast" <nomail@invalid.com> a écrit dans le message de news:568e3fb4$0$659$426a74cc@news.free.fr...

Thank you for answers.
That's clear now. 

[toc] | [prev] | [standalone]


Back to top | Article view | comp.lang.python


csiph-web