Image from Wikimedia

Where’s Wally?

A Python Brain Teaser

Miki Tebeka
3 min readJun 24, 2022

--

https://pragprog.com/newsletter/

What do you think the following program will print?

This program will print Found Waldo

Why? Let’s start by reading str.find documentation:

str.find(sub[, start[, end]])
Return the lowest index in the string where substring sub is found within the slice s[start:end]. Optional arguments start and end are interpreted as in slice notation. Return -1 if sub is not found.

So, haystack.find(needle) will return -1. Why is -1 considered true? The reason is … history.

The Python most of us use is called “CPython”, it’s written in C and started it’s life in 1991 (yes, Python is that old). At the time, C didn’t have boolean types — they were added in the C99 spec around 2000. Python adopted its truth rules from C. Even today, you can find the following in the official documentation:

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)

Boolean values finally came to Python 2.3 after a long and bitter debate.
But, Python respects the old truth value semantics.

Back to our problem, we get -1 which is considered True. And that’s why you see the Found Waldo output.

Site note: I’ve seen this bug in the wild several times and even committed it myself a couple of times. 😏

What’s the solution? Use the inoperator.

Why does str.find return –1when not found? str.find returns the index of the substring if it is found. Since the substring might be at the start (for example: str.find('Java', 'JavaScript'), 0 can be a valid index. Even though -1 is a valid string index, it’s clear enough that it signals “not found.”

🎓 The lesson here? Read the docs, don’t assume you know what a function returns. The Python community invest a lot of effort to keep the documentation helpful and up to date.

--

--