Pythonで| =(ior)は何をしますか?


112

Googleでは検索を許可しない|=ため、関連するドキュメントを見つけることができません。誰か知ってる?


5
以下のサニーの回答のように、これ|は集合結合演算子としても使用されることを指摘することは適切だと思います
TallChuck

10
2019年、Googleは検索を許可します `| =`!:-)
rbennell

回答:


45

|=オブジェクトのペア間でインプレース+操作を実行します。特に、次の間:

ほとんどの場合、それは|オペレーターに関連しています。以下の例を参照してください。

セット

たとえば、2つの割り当てられたセットの和集合は、次の同等の式s1s2共有します。

>>> s1 = s1 | s12                                          # 1
>>> s1 |= s2                                               # 2
>>> s1.__ior__(s2)                                         # 3

ここで、の最終値s1は次のいずれかと同等です。

  1. 割り当てられたOR演算
  2. インプレースOR演算
  3. 特別なメソッド++によるインプレースOR演算

ここでは、セットに OR(|)とインプレースOR(|=)を適用します

>>> s1 = {"a", "b", "c"}
>>> s2 = {"d", "e", "f"}

>>> # OR, | 
>>> s1 | s2
{'a', 'b', 'c', 'd', 'e', 'f'}
>>> s1                                                     # `s1` is unchanged
{'a', 'b', 'c'}

>>> # Inplace OR, |=
>>> s1 |= s2
>>> s1                                                     # `s1` is reassigned
{'a', 'b', 'c', 'd', 'e', 'f'}

辞書

Python 3.9+、新たなマージ(|)および更新(|=)演算子は、辞書間で提案されています。注:これらは上記の集合演算子と同じではありません。

2枚の割り当てられたdictsの間での操作を考慮するd1d2

>>> d1 = d1 | d2                                           # 1
>>> d1 |= d2                                               # 2

ここで、d1は次と同等です:

  1. 割り当てられたマージ権操作
  2. インプレースマージ権(更新)操作。に相当d1.update(d2)

ここでは、dictsにマージ(|)と更新(|=)を適用します

>>> d1 = {"a": 0, "b": 1, "c": 2}
>>> d2 = {"c": 20, "d": 30}

>>> # Merge, | 
>>> d1 | d2
{"a": 0, "b": 1, "c": 20, "d": 30}
>>> d1 
{"a": 0, "b": 1, "c": 2}

>>> # Update, |=
>>> d1 |= d2
>>> d1 
{"a": 0, "b": 1, "c": 20, "d": 30}

カウンター

collections.Counter呼ばれる数学的なデータ構造に関連しているマルチセット(MSET)。これは基本的に、(オブジェクト、多重度)キーと値のペアのディクテーションです。

割り当てられた2つのカウンターc1との間の操作を指定c2

>>> c1 = c1 | c2                                           # 1
>>> c1 |= c2                                               # 2

ここで、c1は次と同等です:

  1. 割り当てられた共用体演算
  2. インプレースユニオン操作

マルチセット和集合には、エントリごとの最大多重度が含まれています。これは、2つのセット間または2つの通常の辞書間と同じように動作しないことに注意してください。

ここでは、カウンターに|ユニオン(|=)とインプレースユニオン()を適用します。

import collections as ct


>>> c1 = ct.Counter({2: 2, 3: 3})
>>> c2 = ct.Counter({1: 1, 3: 5})

>>> # Union, |    
>>> c1 | c2
Counter({2: 2, 3: 5, 1: 1})
>>> c1
Counter({2: 2, 3: 3})

>>> # Inplace Union, |=
>>> c1 |= c2
>>> c1
Counter({2: 2, 3: 5, 1: 1})

数字

最後に、バイナリ演算を行うことができます。

2つの割り当てられた数値n1との間の操作を指定n2

>>> n1 = n1 | n2                                           # 1
>>> n1 |= n2                                               # 2

ここで、n1は次と同等です:

  1. 割り当てられたビットごとのOR演算
  2. インプレースのビットごとのOR演算

ここでは、ビットごとのOR(|)とインプレースのビットごとのOR(|=)を数値に適用ます

>>> n1 = 0
>>> n2 = 1

>>> # Bitwise OR, |
>>> n1 | n2
1
>>> n1
0

>>> # Inplace Bitwise OR, |=
>>> n1 |= n2
>>> n1
1

レビュー

このセクションでは、ビットごとの数学について簡単に説明します。最も単純なケースでは、ビット単位のOR演算は2つのバイナリビットを比較します。1両方のビットがの場合を除いて、常に戻ります0

>>> assert 1 == (1 | 1) == (1 | 0) == (0 | 1)
>>> assert 0 == (0 | 0)

このアイデアを2進数に拡張しました。任意の2つの整数(小数部の欠落)が与えられた場合、ビット単位のORを適用して、整数の結果を取得します。

>>> a = 10 
>>> b = 16 
>>> a | b
26

どうやって?一般に、ビット単位の演算はいくつかの「規則」に従います。

  1. 同等のバイナリを内部的に比較する
  2. 操作を適用する
  3. 指定された型として結果を返します

これらのルールを上記の通常の整数に適用してみましょう。

(1)ここでは文字列(0bバイナリを示す)として見られるバイナリの同等のものを比較します。

>>> bin(a)
'0b1010'
>>> bin(b)
'0b10000'

(2)各列にビットごとのOR演算を適用します(0両方の場合0、そうでない場合1):

01010
10000
-----
11010

(3)与えられた型で結果を返します。

>>> int(0b11010)
26

内部のバイナリ比較は、後者を任意の底の整数に適用できることを意味します。

>>> c = 0xa
>>> d = 0o32
>>> c | d
26

こちらもご覧ください

+ インプレースのビットごとのOR演算子はリテラルに適用できません。オブジェクトを名前に割り当てます。

++ 特別なメソッドは、対応する演算子と同じ演算を返します。


2
完全に明確にするために、通常の割り当て(x = x | y)を実行した後、id(x)は新しいオブジェクトであるために変更され、| =は元のxであるため同じIDを保持することをデモンストレーションに追加します変更されたため、「インプレース」という名前。
Florimond

1
これが一番の答えになるはずです-それは最も徹底的です。
ニック

数値セクションでは、2番目のステートメントがインプレース操作を行うと主張しています。intPythonではは変更できないので、私はそれは本当ではないと思います。
Asocia

106

Pythonや他の多くのプログラミング言語で|は、ビット単位のOR演算です。|=ある|よう+=であり+、すなわち操作とasignmentの組み合わせは、。

var |= value略ですvar = var | value

一般的な使用例は、2つのセットをマージすることです。

>>> a = {1,2}; a |= {3,4}; print(a)
{1, 2, 3, 4}

21
例を挙げていただけますか?
ミネラル

私が以下で遭遇した1つのユースケースを示しています
scharfmn

53

セットで使用すると、ユニオン演算を実行します。


1
私はいくつかのコードを読ん|=でいて、それがセットコンテキストで使用されていましたが、この答えもここにあることに気づいたのは、私がいじり回ってそれを理解するまででした
TallChuck

41

これは、現在の変数と他の変数との単なるOR演算です。ビーイングT=TrueF=False、グラフィカル出力を参照してください。

r    s    r|=s
--------------
T    T    T
T    F    T
F    T    T
F    F    F

例えば:

>>> r=True
>>> r|=False
>>> r
True
>>> r=False
>>> r|=False
>>> r
False
>>> r|=True
>>> r
True

7
これは、オペレーターに一種の歪んだ印象を与えます。|整数のビットごとのOR演算子であり、特にブール演算子ではありません。s以外boolの場合は、実際には生成TrueまたはFalse出力されません。boolはのサブクラスでintあり、適切にオーバーロードされboolTrue/ False出力を生成し続けますが、ほとんどの場合、ブール演算はででorはなくで実行する必要があり|ます。の通常の用途は|、ビット単位の論理和、または集合和です。より良い使用例は、がa = 0b1001; a |= 0b0010; print(bin(a))生成するようなもの0b1011です。
ShadowRanger 2018年


3

それはビットごとです。32 |= 10画像32と10がバイナリであるとしましょう。

32 = 10 0000
10 = 00 1010

今| isまたは、ビットごとまたは2つの数値に対して

つまり、1または0-> 1、0または0-> 0です。これをチェーンで続けます

10 0000 | 00 1010 = 10 1010.

次に、バイナリを10進数に変更します(10 1010 = 42)。

| =については、既知の例を考えてみてくださいx +=5。それは意味x = x + 5,私たちが持っている場合、したがってx |= 5、それは意味しますx = x bitwiseor with 5


これは私が探していた説明です。誰もがセットとブールについて話しましたが、数値での使用について誰も言及していませんでした。
Ankush Verma

あなたが挙げた例は32 |= 10、むしろそうではありません 32 | 10。将来の読者のためにこれを明確にするために:)
sniper71 '29

@ sniper71 32の結果は何ですか| = 10
Future-Jim

2

ユースケースを与えるには(他の回答に時間を費やした後):

def process(item):
   return bool(item) # imagine some sort of complex processing taking place above

def any_success(data): # return True if at least one is successful
    at_least_one = False
    for item in data:
       at_least_one |= process(item)
    return at_least_one

>>> any_success([False, False, False])
False
>>> any_success([True, False, False])
True
>>> any_success([False, True, False])
True

基本的にany短絡なし:すべてのアイテムを処理し、少なくとも1つの成功などを記録する必要がある場合に便利です。

この回答の警告も参照してください


1

Pythonでは、| =(ior)はユニオン演算のように機能します。たとえば、x = 5とx | = 5の場合、両方の値が最初にバイナリ値に変換され、次に結合演算が実行されて、答えが5になります。

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