2

I understand that Python built-in types have a "truthiness" value, and the empty string is considered False, while any non-empty string is considered True.

This makes sense

I can check this using the built-in function bool.

>>> bool("")
False

>>> bool("dog")
True

I can also make use of these truthiness values when using conditionals. For example:

>>> if "dog":
...     print("yes")
...
yes

This is confusing

This doesn't work with the == operator though:

>>> "dog" == True
False

>>> "dog" == False
False

Can anyone explain why == seems to act differently than a conditional?

martineau
  • 119,623
  • 25
  • 170
  • 301
Dustin Michels
  • 2,951
  • 2
  • 19
  • 31

3 Answers3

2

See the truth value testing and comparisons sections of the documentation, excerpted below.

In a nutshell, most things are truthy by default, which is why bool("dog") is true. The == operator compares two objects for equality, as opposed to comparing their truthinesses, as I assume you had expected.

4.1. Truth Value Testing

Any object can be tested for truth value, for use in an if or while condition or as operand of the Boolean operations below.

By default, an object is considered true unless its class defines either a __bool__() method that returns False or a __len__() method that returns zero, when called with the object.

Here are most of the built-in objects considered false:

  • constants defined to be false: None and False
  • zero of any numeric type: 0, 0.0, 0j, Decimal(0), Fraction(0, 1)
  • empty sequences and collections: '', (), [], {}, set(), range(0)

Operations and built-in functions that have a Boolean result always return 0 or False for false and 1 or True for true, unless otherwise stated. (Important exception: the Boolean operations or and and always return one of their operands.)

4.3. Comparisons

Objects of different types, except different numeric types, never compare equal.

...

Non-identical instances of a class normally compare as non-equal unless the class defines the __eq__() method.

MarredCheese
  • 17,541
  • 8
  • 92
  • 91
1

The basics

I believe your confusion might come from comparing Python to languages such as JavaScript where there is a == and a === operator. Python does not work this way.

In Python the only way to compare for equality is with == and this compares both value and type.

Thus if you compare True == "dog", then the expression is immediately False because the types bool and str are not types that can be compared.

Although, note that it does not mean that there are no types that are comparable between themselves. Examples are set and frozenset:

frozenset({1,2,3}) == {1,2,3} # True

Or simply int and float

1 == 1.0 # True

This is the behaviour for most built-in types.

The classy part

In the case where you define your own types, i.e. when you define classes, you can write the __eq__ which is called when you compare a class object to another value.

By example you could do this (which by the way was pointed out as a terrible idea in the comments, you should not inherit built-in types).

class WeirdString(str):
    def __eq__(self, other):
        return str(self) == str(other) or bool(self) == bool(other)

s = WeirdString("dog")
s == True # True

In the case where you do not define __eq__, then Python fall back on comparing whether the objects are the same object with is.

Olivier Melançon
  • 21,584
  • 4
  • 41
  • 73
  • For those who wonder why I say *for most built-in types*, I was thinking of shady stuff like this: https://docs.python.org/3/library/stdtypes.html#memoryview.__eq__ – Olivier Melançon Feb 28 '18 at 04:43
  • 1
    To be clear, `WeirdString` is a *terrible* idea. `s` in this case will be equal to `"foo"`, `{1}`, `[1]`, `-200.5`, `{'a': 1}`, `object()`, etc. Python is strongly typed for a reason; with dynamic typing already in play, weak typing makes it nigh impossible to write code you can reason about usefully. The real lesson here is to write idiomatic code, which *never* uses `== True` or `== False`, and just use implicit truthiness. – ShadowRanger Feb 28 '18 at 04:46
  • It is a terrible idea, I will mention this to be clear. – Olivier Melançon Feb 28 '18 at 04:47
  • Also, standard `==` is not testing type explicitly. Different numeric types are comparable, `set` can be compared to `frozenset`, many bytes-like types compare to each other as expected, etc. Don't bring in the explicit type checking of JS's `===` here, it just confuses the matter. – ShadowRanger Feb 28 '18 at 04:48
  • I reworked my answer to include your remarks, that are on point by the way. – Olivier Melançon Feb 28 '18 at 04:54
0

When you compare "dog" == True, you are also comparing the type of these objects and not just their boolean value.

Now as True has a type bool and "dog" has a type str, they are not equivalent according to the == operator, irrespective of their boolean values being equal.

Note: Both the object's type,boolean values are being checked here.

Ubdus Samad
  • 1,218
  • 1
  • 15
  • 27