Pythonのブーリアンに関する混乱しやすい挙動

# coding: utf-8

lst = [True, False, None]

def f(index):
    try:
        print lst.index(index)
    except Exception, e:
        print "exception was raised: ", e

# False,True,Noneそれぞれに対してインデクシングすると
# それぞれ1,0,2が返り値
f(False)
f(True)
f(None)

# リストに無い値をインデクシングしようとするとValueErrorが送出される
f(34)

# じゃあ、1ではどうなるだろうか?
# リストの要素に1は含まれないのでエラーが送出されるはず。
f(1)

出力結果

1
0
2
exception was raised:  list.index(x): x not in list
0

リストに含まれないはずの1のインデクシングでエラーが送出されず、その代わりに0が返った。

原因

Pythonでは1=Trueなのでlst.index(index)の返り値は0になる。また、Falseは0と等しくlst.index(0)の返り値は1になる。

$ python
Python 2.5.4 (r254:67916, Oct  6 2009, 20:05:55) 
[GCC 4.0.1 (Apple Inc. build 5493)] on darwin
Type "help", "copyright", "credits" or "license" for more information.
>>> True == 1
True
>>> False == 0
True

ここまで単純化されているとまだ分かりやすいが、リストの要素やインデクスが関数呼び出しやメソッド呼び出しの結果であったりすると再現性が低くなったりプログラムの字面からブーリアンリテラルが消えて混乱する。