Pythonで偽と見なされる値

Python のライブラリリファレンス5.1. 真理値テストには、次の値が偽と判定されると書いてある。

  • None
  • False
  • 数値におけるゼロ。例えば 0, 0L, 0.0, 0j 。
  • 空のシーケンス型。例えば ”, (), [] 。
  • 空のマッピング型。例えば {} 。
  • __nonzero__() または __len__() メソッドが定義されているようなユーザ定義クラスのインスタンスで、それらのメソッドが整数値ゼロまたは bool 値の False を返すとき。

そこで、まず次のようなスクリプトを書いて確かめてみた。

def istrue(val):
    if val:
        print "true"
    else:
        print "false"

print "number 0:", istrue(0)

print "empty string \"\":", istrue("")

print "empty list []:", istrue([])

print "empty tuple ():", istrue(())

print "empty dictionary {}:", istrue({})

print "False:", istrue(False)

print "None:", istrue(None)

実行:

^o^ > python false.py
number 0: false
empty string "": false
empty list []: false
empty tuple (): false
empty dictionary {}: false
False: false
None: false

予想通りすべて false を返した。

もうひとつ、__nonzero__メソッドや__len__メソッドを持ったオブジェクトで試してみよう。Fooクラスは真になり、Barクラスは偽になるようにしてみる。

class Foo:
    def __nonzero__(self):
        return True

class Bar:
    def __len__(self):
        return 0

def istrue(val):
    if val:
        print "true"
    else:
        print "false"

print "Foo:", istrue(Foo())

print "Bar:", istrue(Bar())

実行:

^o^ > python true_or_false.py
Foo: true
Bar: false

これも予想通り、Foo は true を返し、Bar は false を返した。

ところで、__nonzero__ と __len__ の両方を持っていて、返す値が矛盾する場合はどうなるんだろう。Bazクラスは__nonzero__ に対しては True を返し、__len__ に対しては 0 を返す。

class Baz:
    def __nonzero__(self):
        return True

    def __len__(self):
        return 0

def istrue(val):
    if val:
        print "true"
    else:
        print "false"

print "Baz:", istrue(Baz()) 

実行:

^o^ > python true_or_false2.py
Baz: true

結果は true だった。どうやら __nonzero__ のほうが優先するみたいだ。