find first bad version
Obligatory PEP 8 reminder:


Whitespace is important.
Whitespace is important too.
Recommendations state that you should:


Design exception hierarchies based on the distinctions that code catching the exceptions is likely to need, rather than the locations where the exceptions are raised. Aim to answer the question "What went wrong?" programmatically, rather than only stating that "A problem occurred" (see PEP 3151 for an example of this lesson being learned for the builtin exception hierarchy);
Not compare boolean values to True or False using == .

Yes:   if greeting:
No:    if greeting == True:
Worse: if greeting is True:




Applying that to your code gives the more readable:

class NoBadVersion(Exception):
    pass


def isBadVersion(number):
    """Mocked external API. Obligatory camelCaseName for consistency."""
    return number &gt; 0


def find_bad_version(numbers):
    """Return the index of the first bad version.
    Tries to perform as few external API calls as possible.
    """

    start = 0
    end = len(numbers) - 1

    if isBadVersion(numbers[start]):
        return start

    if not isBadVersion(numbers[end]):
        raise NoBadVersion('all good')

    while start &lt;= end:
        mid = start + (end-start) / 2
        if isBadVersion(numbers[mid]):
            if start == end:
                return end
            end = mid
        else:
            start = mid + 1


if __name__ == "__main__":
    print find_bad_version([0, 0, 0, 1, 1, 1, 1, 1])
    print find_bad_version([0, 0, 0, 0, 0, 0, 0, 1])