'' と None は違うのだ

Python のイディオムで、こういうのがある。

f = open('file.txt')
whlie 1:
    line = f.readline()
    if not line:
        break
    process(line)

これは、ファイルの終端(EOF)になると readline() が '' (空文字列) を返し、'' は論理値を期待する文脈で False と解釈されることを利用している。ちなみに None も同じ状況で False と解釈されるので、ちょっとした誤解が生じる(かも知れない)。
というのは、あくまでも EOF で readline() が返すのは '' であって、None や False ではないのだ。以下の条件式は絶対に True にならない。(ここで、'/dev/null' は Unix で常に EOF を返す特殊ファイル。)

>>> '' == False
False
>>> None == False
False

しかし、論理値を期待する文脈では False として解釈されるので、次は True になる。

>>> not ''
True
>>> not None
True

知っている人には当たり前かも知れないが、マニュアルをよーく読まないと失敗するはめになる。注意しよう。ちなみに蛇足だが、1 と True、0 と False はほとんどの文脈で等価だ*1。だから、次は True になる。

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

しかし、組込関数*2 type() を適用すると、これらは区別される。

>>> type(True)
<type 'bool'>
>>> type(1)
<type 'int'>
>>> type(None)
<type 'NoneType'>
>>> type('')
<type 'str'>

気をつけよう。

file 型補足

通りがかりの人に、Python 2.2 以降では file 型がイテレータiterator)になっているので、次のように書いたほうが便利だと教えて頂きました。

f = open('file.txt')
try:
    for line in f:
        process(line)
finally:
    f.close()

ちなみに、for line in open('file.txt'): と書くと明示的なクローズができなくなるので、厳密には上のように書いたほうが良いようです。Python 2.6 以降で(あるいは 2.5 で from __future__ import with_statement した場合)は、

with open('file.txt') as f:
    for line in f:
        process(line)

のようにすることで、with 文から抜けるとファイルが自動的にクローズされるのだそうですが、なんだか全然分からん。

type() 補足

ちなみに、type(a) で a の型(a に代入されている型)が分かると書きましたが、コード中で a の型によって処理を分岐したり例外を上げたりしたいとき、isinstance() という組込関数が使えます。

>>> a = ''  
>>> if isinstance(a, str):
...     print "string"
... elif isinstance(a, int):
...     print "integer"
... else:
...     print "other type"
... 
string

ちなみに、isinstance(type, type) == True のようです。また、None かどうかの比較に isinstance(a, none) とかは書けないようで、a == None、とするしかないようです。(リファレンスマニュアルによると、None の型は唯一の値である None しか持たないということなので、これで良いのでしょう。)

*1:これは C 言語に近い。

*2:正確には関数じゃないらしい。