2013-04-05 32 views
8

私はいくつかのかなりcruftyコードをリファクタリングして、次の奇妙構造に出くわしてきた:(FOOまたはバーやバズ)がある場合なし:

#!/usr/bin/env python2.7 
# ... 
if (opts.foo or opts.bar or opts.baz) is None: 
    # (actual option names changed to protect the guilty) 
    sys.stderr.write("Some error messages that these are required arguments") 

...と、これは今までならば、私は思っていました考えられる感覚を作る。

私のような何かにそれを変更:唯一の値は、すべての最後の偽とであれば動作しているようです...私は通訳を起動し、実際には最初の構造をしてみてくださいでした

#!/usr/bin/env python2.7 
if None in (opts.foo, opts.bar, opts.baz): 
    # ... 

これらの偽の値はNoneです。 (つまり、CPythonの実装は、またはの式のチェーンから最初の真偽または最後の偽の値を返すようです。

私はまだ適切なコードは2.5を追加された任意の()またはすべて()組み込み関数(問題のコードはすでに2.7が必要です)のいずれかを使用する必要があると思われます。私はこのプロジェクトをちょうど始めているので、どちらが望ましい/意図されたセマンティクスであるかまだ分かりません。

この元のコードが意味をなさない場合はありますか?

+0

あなたの第一の条件は、あなたのすべての変数はいずれも

In [19]: (None or None or None) is None Out[19]: True 

されていないときに、あなたがあなたの最初の条件を書き換えることができますTrueを返します。これを修正して新しいバグを導入しないように注意してください:) –

答えて

5

短絡動作により、foo or bar or bazは、boolean-trueの3つの値のうち最初の値を返します。また、すべてがboolean-falseの場合は最後の値を返します。つまり、基本的には「すべてが偽で、最後のものが「なし」」を意味します。

変更されたバージョンは若干異なります。 if None in (opts.foo, opts.bar, opts.baz)は、opts.fooがNoneで他の2つが1の場合はifブロックを入力します(None or 1 or 1はNoneではないため、元のバージョンは無効です)。お使いのバージョンでは、3のどのは関係なく、元のバージョンがifに入ることになるのに対し、他の2つは、あるもののいずれもが、ないとき最後はなしない場合ifだけ他の2つは任意のboolean-ある入ります偽の値。

残りのコードの構造とオプションがとりうる値によって異なります(特に、Falseまたは0のような[なし]以外のブール値または偽の値を持つ可能性があるかどうか、または空の文字列)。直感的には、あなたのバージョンはより合理的ですが、コードにこのような特有のトリックがある場合、コーナーケースがどのように現れるかも知れません。

5

orが短絡オペレータであるため、そのように動作します。詳細はdocsです。我々が期待しているコードのどのような著者を推測することができ

if opts.baz is None 

:したがって、あなたの最初のif文はに等しいです。あなたが言及したように、彼はnot all([opts.foo, opts.bar, opts.baz])を使用することを考えました。

+1

彼の質問に具体的に答えるには:コードが間違っているように見えますが、それは意味をなさないケースを考えることができません。 – Anorov

+1

"is"演算子がない場合は意味があります。しかし、これは技術的にはすべての値がfalse *と評価された場合にテストされます。*最後のものは、特にNoneシングルトンへの参照です。 –

+0

@JimDennis確かに – Anorov

0

それが正確に意図した目標を表現するように私は

if any(i is None for i in (opts.foo, opts.bar, opts.baz)) 

を好むだろう。

OTOH、

not all([opts.foo, opts.bar, opts.baz]) 

はないNoneため、真偽をチェックしません。

元のコードは意味をなさないと思われます。彼らは何をしているのか知らない人によって書かれたようです。

0

はのは、あなたのコードの両方2を試してみましょう:

In [20]: foo = True 

In [22]: bar = None 

In [23]: baz = None 

In [24]: foo or bar or baz 
Out[24]: True 

In [25]: (foo or bar or baz) is None 
Out[25]: False 

In [28]: ((foo or bar or baz) is None) == (None in (foo, bar, baz)) 
Out[28]: False 

あなたのリライトが元のコードと同じではありません見ることができます。ひどいです

if foo == bar == bar == None: 
+0

私はセマンティクスが異なっていることを認めました。ここでのポイントは、元のセマンティクスが正しいと思われる場合があるかどうかを推測することです。 私は、幸いなことに、決して実際には気付かれていないような、さまざまなコーナーケースで前のコードが失敗したと思います。 (これは非常に少数のスタッフによってのみ使用された内部コマンドラインユーティリティの一部です)。 –

関連する問題