PythonにはRubyの|| =のような「または等しい」関数がありますか?


83

そうでない場合、これを行うための最良の方法は何ですか?

今私は(djangoプロジェクトのために)やっています:

if not 'thing_for_purpose' in request.session:
    request.session['thing_for_purpose'] = 5

しかし、それはかなり厄介です。Rubyでは次のようになります。

request.session['thing_for_purpose'] ||= 5

これははるかに良いです。


23
これらの2ビットのコードは実際には非常に異なることに注意してください。Pythonバージョンは、dictにまったく含まれていない場合は5に設定し、Rubyバージョンもfalse値に設定されている場合は5に設定します。
グレンメイナード

2
@Glenn、それほど違いはありませんが、かなり違います。初期化されていないハッシュ値が返されるためnil(ブール値のコンテキストではfalse)、このイディオムは、seanが使用した目的のために正確に使用されることがよくあります。イディオムは場合にのみものの、もちろん、作品、nilおよびfalse(非常に頻繁に本当であるので、イディオムで結構です)のハッシュで合法的な値ではありません
horseyguy

8
@banister:「非常に」と「かなり」の間に線を引く場所はわかりませんが、重要なのは、これらは同等のステートメントではないため、違いを理解することが重要です。(Falseはハッシュ内の有効な値であることが非常に多く、ブールフィールドのデフォルトをtrueに設定するときに噛み付きます。これは、Rubyのイディオムの重大な欠点です。)
Glenn Maynard

はい、Pythonの例はdefinedに似て//=います-またはperlにあるようなものです。これ||=もPerlに由来すると思います。
draegtun 2010年

ああ良い点、すべて。私はこの違いに気づいていませんでした。
ショーンW.

回答:


188

受け入れられた答えは口述に適していますが、タイトルはRubyの|| =演算子と一般的に同等のものを求めています。Pythonで|| =のようなことをする一般的な方法は

x = x or new_value

36
この答えは、Google検索からここに来る人々が探しているものである可能性があります。
gradi3nt 2014

これは本当に最良の答えです。
AdamC 2015年

6
Rubyとは異なり、このコードはx以前に定義されている場合にのみ機能することに注意してください(たとえばNone、クラス初期化メソッドでに設定されている)。
oli 2016年

3
確かに、これはRubyの|| =とまったく同じようには動作しません。注意すべきもう1つのことは、xの「真実性」です。Pythonでのx == 0の場合は0がfalseと見なされますが、Rubyでは、あなたが0に取得しますので、あなたはNEW_VALUEを取得します
ジョセフ・シーディ

1
これは|| =と同じくらい効率的ですか?|| = nullでない限り割り当ては行いませんが、これは常に割り当てを行います。Pythonコンパイラは私が思っているよりも賢いですか?
jsarma 2016

17

dict持っていsetdefault()ます。

もしそうであればrequest.sessionありますdict

request.session.setdefault('thing_for_purpose', 5)

漠然と似ていますが、Rubyの|| =とまったく同じではありません。
AdamC 2015年

1
キーがすでに設定されている場合でも、デフォルトの式が評価されるという点で大きく異なります。デフォルト値を評価するか、キーに複数回アクセスするか、またはその両方を行わずに、元の質問を解決する方法はありません。
slinkp 2018

13

正確な答えは:いいえ Pythonは、単一のないビルトイン演算子op翻訳することができますx = x or yx op y

しかし、ほとんどそうです。 ビットごとのor-equals演算子(|=、両方のオペランドがブール値として扱われている場合、上記のように機能しますが、注意が必要です。(注意点は何ですか?答えはもちろん以下です。)

まず、機能の基本的なデモンストレーション:

x = True
x    
Out[141]: True

x |= True
x    
Out[142]: True

x |= False
x    
Out[143]: True

x &= False
x    
Out[144]: False

x &= True
x    
Out[145]: False

x |= False
x    
Out[146]: False

x |= True
x   
Out[147]: True

警告は、Pythonが厳密に型指定されていないためです。したがって、値が式でブール値として扱われている場合でも、ビット演算子に指定された場合、値は短絡されません。たとえば、リストをクリアし、True要素が削除された場合に返すブール関数があるとします。

def  my_clear_list(lst):
    if not lst:
        return False
    else:
        del lst[:]
        return True

これで、短絡した動作を次のように確認できます。

x = True
lst = [1, 2, 3]
x = x or my_clear_list(lst)
print(x, lst)

Output: True [1, 2, 3]

ただし、をorビット単位または(|)に切り替えると短絡が解消されるため、関数がmy_clear_list実行されます。

x = True
lst = [1, 2, 3]
x = x | my_clear_list(lst)
print(x, lst)

Output: True []

上記は、x = x | my_clear_list(lst)と同等x |= my_clear_list(lst)です。


10

ミドルウェアなどでデフォルトを設定することは理にかなっていますが、1つのリクエストのコンテキストでデフォルト値が必要な場合は次のようになります。

request.session.get('thing_for_purpose', 5) # gets a default

ボーナス:||=Pythonで実際にを行う方法は次のとおりです。

def test_function(self, d=None):
    'a simple test function'
    d = d or {}

    # ... do things with d and return ...

1

一般的には、を使用できますdict[key] = dict.get(key, 0) + val

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