Pythonでは、変数がNone、True、またはFalseであるかどうかをどのようにテストすればよいですか


146

次の3つのいずれかを返すことができる関数があります。

  • 成功(True
  • 失敗(False
  • ストリームの読み取り/解析エラー(None

私の質問は、Trueまたはに対してテストすることになっていない場合False、結果がどうなるかをどのように見ればよいかです。以下は私が現在それをやっている方法です:

result = simulate(open("myfile"))
if result == None:
    print "error parsing stream"
elif result == True: # shouldn't do this
    print "result pass"
else:
    print "result fail"

== Trueパーツを削除するのと同じくらい簡単ですか、それともトライブールデータタイプを追加する必要がありますか。simulate外部プログラムでエラーを処理するためにログに記録して続行するだけなので、関数に例外をスローさせたくありません。


あなたは間違った質問をしています。あなたはあなたの結果を定義する助けを求めているはずです...あなたが「失敗」と「エラー解析ストリーム」との間で知覚する違いは何ですか、それらは何を意味しますか、結果は何ですかどちらの場合でも(合格、失敗、解析エラー)?
John Machin

私は電力システムをシミュレーションしていますが、人々が家の電源を失った場合、それは失敗です。シミュレーションファイルを読み取れない場合は、まったく別の種類のエラーです。
James Brooks

2
simulate関数内ですべての例外をキャッチします。シミュレーター内で何が起こっても、残りのプログラムの実行を停止(および次の要素を処理)したくありません。しかし、答えは私の心を変えさせています。
James Brooks

1
@ジェームス・ブルックス:そうです。それがtry / except処理のすべてです。simulateキャッチして再試行できるものがあれば、それは良いことです。しかし、それが「失敗」した場合は、戻りませんNone。それを呼び出したスクリプトに例外を発生させるだけです。どちらにしても、simulate完了です。戻ることNoneは、適切な例外を発生させるほど役立ちません-または、例外をsimulate呼び出しスクリプトに伝播して処理することができます。
S.Lott

1
@James、except Exception:代わりに使用してください。これは、Warningおよびとともに、すべての「実際の」エラーをキャッチしますStopIteration。それは可能にKeyboardInterruptし、SystemExitしかし通じ。これらを「エラー」ではないため、本当にキャッチしたい場合は、意図を明確に文書化した別の外部try / exceptまたはその他の構造を使用することをお勧めします。(しかし、私は「ほとんど決してしなかった」と言いました...おそらくあなたの場合、あなたは本当にすべてをつかんで、Ctrl-C sys.exit()を終了したり、終了したりすることさえしたいと思っています。)
Peter Hansen

回答:


119

例外を恐れるな!プログラムをログに記録して続行させるのは、次のように簡単です。

try:
    result = simulate(open("myfile"))
except SimulationException as sim_exc:
    print "error parsing stream", sim_exc
else:
    if result:
        print "result pass"
    else:
        print "result fail"

# execution continues from here, regardless of exception or not

また、エラー/エラーなしでは十分な情報が得られない場合に備えて、正確に何が問題だったかについて、simulateメソッドからの通知の種類を大幅に増やすことができます。


同意した。上記の明らかに人気のあるソリューション(Cコードのように臭いがする)よりもはるかにPython的です。
Brandon

7
@Brandon同意されていません。このコードは、上記の解決策(または以下の改良版)よりも長く、悪いことに、読みにくくなります。インデントが増え、ステートメントの種類が増えます。それがより厄介なコードにつながる場合は「Pythonic」...?
Rolf Bartstra

ここで、「エラー解析ストリーム」の代わりにトレースバックを出力すると、私の投票が得られます。
CivFan 2015年

とにかくあなたは私の投票を得ましたが、私はのようなものを印刷することを意味しましたtraceback.format_exc() このSOの答えを見てください。
CivFan 2015年

10
タイトルの質問に対する答えを探して、多くの人がこのページにアクセスします。私たちのほとんどにとって、「例外を恐れないでください!」私たちの状況とは何の関係もありません。True、False、Noneをテストするだけです。提案された代替案はいくつかのケースで有効ですが、質問されたとおりに質問への回答も含めるのが最善だと思います。
非常に優れた人物、2016年

162
if result is None:
    print "error parsing stream"
elif result:
    print "result pass"
else:
    print "result fail"

シンプルかつ明確にしてください。もちろん、辞書を事前に定義することもできます。

messages = {None: 'error', True: 'pass', False: 'fail'}
print messages[result]

simulateより多くの戻りコードを含めるように関数を変更することを計画している場合、このコードの保守は少し問題になるかもしれません。

またsimulate、解析エラーで例外が発生する場合があります。その場合、ここでそれをキャッチするか、レベルを上げて、出力ビットを1行のif-elseステートメントに減らします。


1
後者は、真または偽に対する明示的なテストの一種ですよね。
Peter Eisentraut、2010年

1
もちろん、これらは可能な戻り値に過ぎないことを知っているので、問題ではないと思います。
SilentGhost 2010年

そして、それも少し速いようです
SilentGhost

a = 'foo' if a:print 'its true' a is not true TRUE、it
is

17

決して、決して、決して言わない

if something == True:

決して。ifステートメントの冗長条件ルールとして冗長に指定されているものを冗長に繰り返しているので、それはクレイジーです。

さらに悪いことに、まだ、決して、決して、決して言わない

if something == False:

あなたが持っていnotます。お気軽にご利用ください。

最後に、行うことa == Noneは非効率的です。してくださいa is NoneNone特別なシングルトンオブジェクトです。1つしか存在できません。そのオブジェクトがあるかどうかを確認してください。


3
との等価性のテストTrueは冗長ではありません(ただし、それは賢明ではないと同意します)。それは__eq__、実質的に何でもできる、または他の特別なメソッドを呼び出すことである可能性があります。
スコットグリフィス

5
@スコットグリフィス:良い点。これは本当に恐ろしいシナリオです。そうだとすれば、プログラムは私たちの基本的な期待に反しており、そのような黒魔術を使わずに単に削除して最初から書き直す必要があるものになっています。
S.Lott、2008年

78
「決して、決して、決して」...?ただし、非ブール値などの場合if something == Trueとは異なる結果が生じる場合もあります。falseを生成し、trueと評価します。偽ですが本当です!if somethingsomething2==True2None==Falsenot None
Rolf Bartstra

9
-1 @Rolf Bartstraの言うことが真実であるため、この答えは誤解を招くものであり、完全に正しくありません。この場合でも、あなたが言うことは適用できます。
HelloGoodbye 2014年

3
-1。ゼロ以外の、空ではない、または長さが0以外の値は、からsomething返さTruebool(something)ます。その場合、something値がTrueie かどうかを確認するだけの場合bool。次に、if something == TrueIMO を実行する必要があります。
Samarth Shah 2015

2

私は状況があっても、それを強調したいif expr :1を確認するために望んでいるので、十分ではないexprですTrueからわずかに異なるといない0/ None何でも、/ isから好まする== S.Lottを回避するためmentionned同じ理由は、== None

それは確かに少し効率的であり、ケーキのチェリーで、より人間が読みやすいです。

In [1]: %timeit (1 == 1) == True
38.1 ns ± 0.116 ns per loop (mean ± std. dev. of 7 runs, 10000000 loops each)

In [2]: %timeit (1 == 1) is True
33.7 ns ± 0.141 ns per loop (mean ± std. dev. of 7 runs, 10000000 loops each)

1
ベンチマークを一度実行して、1つが他のベンチマークよりも効率的であると言うことはできません(たとえそうであっても)。何度も実行(10.000)して、平均的な動作を確認します。\
user1767754

1

例外をスローする方があなたの状況に適していると思います。別の方法は、タプルを返すシミュレーションメソッドです。最初の項目はステータスで、2番目の項目は結果です。

result = simulate(open("myfile"))
if not result[0]:
  print "error parsing stream"
else:
  ret= result[1]

1
タプルを返すことは通常、タプルをアンパックすることでうまくいきます;)
SilentGhost 2010年

2
ただし、コードはあまり意味がありません。False返された場合、出力されます'error parsing stream'
SilentGhost

シミュレーションメソッドは、(False、 "anything at all")または(True、ret)を返す必要があります。retはFalseまたはTrueです。
kgiannakakis

2
さて
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.