2009-04-15 13 views
46

my_varがNoneの場合、次の形式を使用することは悪い習慣ですか?if文の条件評価順序に頼っても安全ですか?

if my_var and 'something' in my_var: 
    #do something 

問題はMY_VARがNoneの場合'something' in my_varはTypeError例外を投げるということです。

それとも私が使用する必要があります。

if my_var: 
    if 'something' in my_var: 
     #do something 

または

try: 
    if 'something' in my_var: 
     #do something 
except TypeError: 
    pass 

上記のパイソン(もしあれば)におけるベストプラクティスです質問を言い換えるするには?

別の方法もあります。

答えて

64

特に、問題点が指摘されているため、条件文の順番に依存することは安全です。条件付き文字列に問題を引き起こす可能性のある評価を短絡できれば非常に便利です。

コードのこの種は、ほとんどの言語でポップアップ表示されます:

IF exists(variable) AND variable.doSomething() 
    THEN ... 
+2

2番目のコードのように見えるとき、コーダーは短絡評価の仕組みを理解していないと思います。 – Dana

+1

-1:ドキュメントの引用はありません:http://docs.python.org/library/stdtypes.html#boolean-operations-and-or-not –

+0

@cfi:回答が変更された後に私の投票を変更できるので、私は問題が何であるかは不明です。 –

1

それは完全に安全だと私はそれをすべての時間を行います。

1

私はtry/exceptを使用しますが、変数について知っているかどうかによって異なります。

ほとんどの場合、変数が存在することが予想される場合、try/exceptはより少ない操作です。ほとんどの場合、変数がNoneになると予想される場合、IF文は操作が少なくなります。

+0

なぜ(可読性、性能など)? – tgray

+0

私は答えを –

27

はい、それはそれは明示的だと非常に明確に言語リファレンスで定義され、安全である:

表現x and yが最初 xを評価します。 xfalseの場合、その値は です。そうでない場合は、yが評価され、 と評価され、結果の値が返されます。

x or yは、最初に xと評価されます。 xが真の場合、その値は です。そうでない場合は、yが評価され、 と評価され、結果の値が返されます。

+1

弱めました:それは "安全"ではありません - それは順序に依存することが絶対に必要です。 –

1

これは簡単ではありません。私はC#の男として、次のようなことにとても慣れています。

if(x != null && ! string.isnullorempty(x.Name)) 
{ 
    //do something 
} 

上記は素晴らしいものであり、期待どおりに評価されています。しかし、VB.Netでは、次の結果はあなたが期待していなかった結果を生成します:

If Not x Is Nothing **And** Not String.IsNullOrEmpty(x.Name) Then 

    'do something 

End If 

上記は例外を生成します。正しい構文は

If Not x Is Nothing **AndAlso** Not String.IsNullOrEmpty(x.Name) Then 

    'do something 

End If 

である必要があります。これは私に約10分間混乱させてしまいました。なぜなら、他の言語でコーディングする場合、C#(と他の)の人たちが非常に注意する必要があるからです。

2

私はここで少し知識をひけらかすされてもよいが、私は最高の答えは

if my_var is not None and 'something' in my_var: 
    #do something 

Noneの明示的なチェックではなく、TrueまたはFalseからmy_varの暗黙的な変換であることの違いであると言うでしょう。

私は変数はNoneことが、まだFalseに評価しないようにするために、より一般的なケースでは、それは十分に可能だろう、あなたのケースで区別は重要ではありません確信しているが、0の例えば整数値または空のリスト

他のポスターの主張とは対照的に、安全であると主張している限り、明示的である限り安全です。

class Contrived(object): 
    def __contains__(self, s): 
     return True 
    def __nonzero__(self): 
     return False 

my_var = Contrived() 
if 'something' in my_var: 
    print "Yes the condition is true" 
if my_var and 'something' in my_var: 
    print "But this statement won't get reached." 
if my_var is not None and 'something' in my_var: 
    print "Whereas this one will." 

はい、私はそれが現実的な例ではありません知っているが、バリエーションが Noneは、デフォルトの関数の引数を示すために使用された場合は特に、実際のコードで起こるのか:あなたは納得していないなら、この非常に不自然なクラスを考えてみましょう。

+0

確かに、空リストやコンテナがあれば、 'in'演算を行うことは無意味です。私はOPにそれが正しいと思う。一方で、ポイントを証明するために何かを構築することは可能ですが、私はまともなコードが足に撃たれるべきではないと信じています。 – SilentGhost

+1

はい、それは人為的な例ですが、私の主なポイントは、もし '' varがNoneではない ''を本当に意味するとき、 ''もし ''と言ってしまうという悪い習慣に入るのは簡単だということです。あなたがその習慣に入ると、それはあなたに簡単に噛み付きます。 –

+0

私は、OPの意図は「もしあれば」と言っていたことが、彼がしたことであることは明らかです。 – SilentGhost