841

Pythonで2つの変数の論理和をどのように取得しますか?

たとえば、文字列であると予想される2つの変数があります。それらの1つだけにTrue値が含まれていることをテストしたい(Noneまたは空の文字列ではない):

str1 = raw_input("Enter string one:")
str2 = raw_input("Enter string two:")
if logical_xor(str1, str2):
    print "ok"
else:
    print "bad"

演算子はビット単位の^ようであり、すべてのオブジェクトで定義されているわけではありません。

>>> 1 ^ 1
0
>>> 2 ^ 1
3
>>> "abc" ^ ""
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
TypeError: unsupported operand type(s) for ^: 'str' and 'str'
4

28 に答える 28

1488

すでに入力をブール値に正規化している場合、!= は xor です。

bool(a) != bool(b)
于 2009-01-11T16:30:46.047 に答える
586

xorの定義をいつでも使用して、他の論理演算から計算できます。

(a and not b) or (not a and b)

しかし、これは私には少し冗長すぎて、一見しただけでは特に明確ではありません。それを行う別の方法は次のとおりです。

bool(a) ^ bool(b)

2つのブール値のxor演算子は、論理xorです(ビット単位のintとは異なります)。boolはのサブクラスであるintため、これは理にかなっていますが、値0と。のみを持つように実装されています1。また、論理xorは、ドメインがとに制限されている場合のビット単位のxorと同等0です1

したがって、logical_xor関数は次のように実装されます。

def logical_xor(str1, str2):
    return bool(str1) ^ bool(str2)

Python-3000メーリングリストのNickCoghlanの功績によるものです。

于 2009-01-11T12:35:51.310 に答える
211

ビット単位の排他的論理和-またはすでにPythonに組み込まれているoperatorモジュール(^演算子と同じ):

from operator import xor
xor(bool(a), bool(b))  # Note: converting to bools is essential
于 2012-06-14T15:34:09.507 に答える
51

ザックが説明したように、次を使用できます。

xor = bool(a) ^ bool(b)

個人的には、少し異なる方言を好みます。

xor = bool(a) + bool(b) == 1

この方言は、私が学校で学んだ論理的な作図言語から着想を得ており、「OR」は≥1(1 以上) を含むボックスで示され、「XOR」は を含むボックスで示されていました=1

これには、複数のオペランドに対して排他的 or を正しく実装できるという利点があります。

  • 「1 = a ^ b ^ c...」は、真のオペランドの数が奇数であることを意味します。この演算子は「パリティ」です。
  • 「1 = a + b + c...」は、ちょうど 1 つのオペランドが true であることを意味します。これは「排他的または」であり、「一方を他方から除外する」という意味です。
于 2009-01-11T13:44:31.840 に答える
33
  • Python logical or::A or BがのA場合bool(A)Trueを返し、そうでない場合は を返しますB
  • Python logical and::A and BがのA場合bool(A)Falseを返し、そうでない場合は を返しますB

その考え方のほとんどを維持するために、私の論理的な xor 定義は次のようになります。

def logical_xor(a, b):
    if bool(a) == bool(b):
        return False
    else:
        return a or b

ab、またはを返すことができますFalse

>>> logical_xor('this', 'that')
False
>>> logical_xor('', '')
False
>>> logical_xor('this', '')
'this'
>>> logical_xor('', 'that')
'that'
于 2009-01-11T13:10:52.860 に答える
28

私はいくつかのアプローチをテストnot a != (not b)しましたが、最速のように見えました。

ここにいくつかのテストがあります

%timeit not a != (not b)
10000000 loops, best of 3: 78.5 ns per loop

%timeit bool(a) != bool(b)
1000000 loops, best of 3: 343 ns per loop

%timeit not a ^ (not b)
10000000 loops, best of 3: 131 ns per loop

編集: 上記の例 1 と 3 には括弧がないため、結果が正しくありません。新しい結果 + truth()ShadowRanger が提案した機能。

%timeit  (not a) ^  (not b)   # 47 ns
%timeit  (not a) != (not b)   # 44.7 ns
%timeit truth(a) != truth(b)  # 116 ns
%timeit  bool(a) != bool(b)   # 190 ns
于 2016-02-04T10:42:56.963 に答える
19

Python にはビットごとの排他的 OR 演算子があります^

>>> True ^ False
True
>>> True ^ True
False
>>> False ^ True
True
>>> False ^ False
False

^xor ( )を適用する前に、入力をブール値に変換することで使用できます。

bool(a) ^ bool(b)

(編集 - Arel に感謝)

于 2019-06-07T09:29:16.720 に答える
12

可変引数を使用し、Truth 値の True または False のみを操作する xor の単純なバリアントは見当たりません。他の人が指摘したように、かなり(非常に言うまでもなく)簡単です。

def xor(*vars):
    result = False
    for v in vars:
        result = result ^ bool(v)
    return result

また、使い方も簡単です。

if xor(False, False, True, False):
    print "Hello World!"

これは一般化された n 項論理 XOR であるため、True オペランドの数が奇数である場合はいつでも真値が True になります (厳密に 1 つが True である場合だけでなく、これは n 項 XOR が True である 1 つのケースにすぎません)。

したがって、オペランドの 1 つだけが True である n 項述語を探している場合は、次のように使用できます。

def isOne(*vars):
    result = False
    for v in vars:
        if result and v:
            return False
        else:
            result = result or v
    return result
于 2010-04-20T13:21:43.987 に答える
10

やりがいのあるスレッド:

別のアイデア...論理的な«xor»の動作を取得するために、(かもしれない)pythonic式«is not»を試すだけです

真理値表は次のようになります。

>>> True is not True
False
>>> True is not False
True
>>> False is not True
True
>>> False is not False
False
>>>

そして、あなたの例の文字列について:

>>> "abc" is not  ""
True
>>> 'abc' is not 'abc' 
False
>>> 'abc' is not '' 
True
>>> '' is not 'abc' 
True
>>> '' is not '' 
False
>>> 

でも; 上記で示したように、文字列はブール演算ではないため、カップル文字列について引き出したい実際の動作に依存します...さらに: «Dive Into Python» を実行すると、«The Peculiar Nature of " and" and "or"» http://www.diveintopython.net/power_of_introspection/and_or.html

書き言葉で申し訳ありませんが、それは私の生まれた言語ではありません。

よろしく。

于 2016-05-20T04:25:11.610 に答える
8

これが遅れていることはわかっていますが、考えがあり、ドキュメントのためだけに価値があるかもしれません. おそらくこれはうまくいくでしょう:np.abs(x-y)アイデアはそれです

  1. x=True=1 かつ y=False=0 の場合、結果は |1-0|=1=True になります。
  2. x=False=0 かつ y=False=0 の場合、結果は |0-0|=0=False になります。
  3. x=True=1 かつ y=True=1 の場合、結果は |1-1|=0=False になります。
  4. x=False=0 かつ y=True=1 の場合、結果は |0-1|=1=True になります。
于 2016-08-01T21:57:05.803 に答える
7

ブール値の True と False の代わりに、1 と 0 を使用していることに気付くことがあります。この場合、xor は次のように定義できます。

z = (x + y) % 2

次の真理値表があります。

     x
   |0|1|
  -+-+-+
  0|0|1|
y -+-+-+
  1|1|0|
  -+-+-+
于 2014-03-08T05:11:44.763 に答える
7

ここで提案されている実装の一部では、場合によってはオペランドの評価が繰り返され、意図しない副作用が発生する可能性があるため、回避する必要があります。

つまり、orxorを返す実装はかなり単純です。可能であれば、オペランドの 1 つを返すものは、特に 3 つ以上のオペランドがある場合に、どのオペランドを選択するかについてコンセンサスが存在しないため、はるかに注意が必要です。たとえば、、または?を返す必要があります。それぞれの答えが最も直感的なものに見える人もいるでしょう。TrueFalsexor(None, -1, [], True)None[]False

True または False の結果のいずれについても、可能な選択肢は 5 つまであります。最後のオペランドを返す (if ... else ...)、最後の一致を返す (if ... else ...)、または常にブール値を返す。全体として、 の 5 ** 2 = 25 フレーバーですxor

def xor(*operands, falsechoice = -2, truechoice = -2):
  """A single-evaluation, multi-operand, full-choice xor implementation
  falsechoice, truechoice: 0 = always bool, +/-1 = first/last operand, +/-2 = first/last match"""
  if not operands:
    raise TypeError('at least one operand expected')
  choices = [falsechoice, truechoice]
  matches = {}
  result = False
  first = True
  value = choice = None
  # avoid using index or slice since operands may be an infinite iterator
  for operand in operands:
    # evaluate each operand once only so as to avoid unintended side effects
    value = bool(operand)
    # the actual xor operation
    result ^= value
    # choice for the current operand, which may or may not match end result
    choice = choices[value]
    # if choice is last match;
    # or last operand and the current operand, in case it is last, matches result;
    # or first operand and the current operand is indeed first;
    # or first match and there hasn't been a match so far
    if choice < -1 or (choice == -1 and value == result) or (choice == 1 and first) or (choice > 1 and value not in matches):
      # store the current operand
      matches[value] = operand
    # next operand will no longer be first
    first = False
  # if choice for result is last operand, but they mismatch
  if (choices[result] == -1) and (result != value):
    return result
  else:
    # return the stored matching operand, if existing, else result as bool
    return matches.get(result, result)

testcases = [
  (-1, None, True, {None: None}, [], 'a'),
  (None, -1, {None: None}, 'a', []),
  (None, -1, True, {None: None}, 'a', []),
  (-1, None, {None: None}, [], 'a')]
choices = {-2: 'last match', -1: 'last operand', 0: 'always bool', 1: 'first operand', 2: 'first match'}
for c in testcases:
  print(c)
  for f in sorted(choices.keys()):
    for t in sorted(choices.keys()):
      x = xor(*c, falsechoice = f, truechoice = t)
      print('f: %d (%s)\tt: %d (%s)\tx: %s' % (f, choices[f], t, choices[t], x))
  print()
于 2009-07-04T09:01:16.170 に答える
7

排他的論理和は次のように定義されます

def xor( a, b ):
    return (a or b) and not (a and b)
于 2009-01-11T13:39:48.387 に答える
6

これはどう?

(not b and a) or (not a and b)

afalse の場合 は与えるfalsebの場合は 与えるそれ以外の場合は与える
ba
False

または、Python 2.5+ の三項式を使用します。

(False if a else b) if b else a
于 2009-01-11T15:29:44.343 に答える
6

A と B がブール値であるとします。

A is not B
于 2021-04-14T13:58:30.417 に答える
5

これは、真理値表をコード化する方法です。特に xor の場合:

| a | b  | xor   |             |
|---|----|-------|-------------|
| T | T  | F     |             |
| T | F  | T     | a and not b |
| F | T  | T     | not a and b |
| F | F  | F     |             |

回答列の T 値を見て、すべての真のケースを論理和でつなぎ合わせます。したがって、この真理値表はケース 2 または 3 で生成される可能性があります。したがって、

xor = lambda a, b: (a and not b) or (not a and b)
于 2020-03-25T23:09:11.707 に答える
5

Xor は^Python です。戻り値:

  • int のビットごとの xor
  • bool の論理 xor
  • セット専用ユニオン
  • を実装するクラスのユーザー定義の結果__xor__
  • 文字列や辞書などの未定義の型の TypeError。

とにかく文字列でそれらを使用する場合は、それらをキャストするとbool、操作が明確になります(意味することもできますset(str1) ^ set(str2))。

于 2019-03-04T15:04:18.833 に答える
4

XORの機能を知っていれば、簡単です。

def logical_xor(a, b):
    return (a and not b) or (not a and b)

test_data = [
  [False, False],
  [False, True],
  [True, False],
  [True, True],
]

for a, b in test_data:
    print '%r xor %s = %r' % (a, b, logical_xor(a, b))
于 2011-02-10T13:34:36.020 に答える
4

これは、2 つ (またはそれ以上) の変数の論理排他的 XOR を取得します。

str1 = raw_input("Enter string one:")
str2 = raw_input("Enter string two:")

any([str1, str2]) and not all([str1, str2])

このセットアップの最初の問題は、リスト全体を 2 回走査する可能性が高く、少なくとも 1 つの要素を 2 回チェックすることです。そのため、コードの理解度が向上する可能性がありますが、速度には役立ちません (ユースケースによっては無視できるほど異なる場合があります)。

このセットアップの 2 つ目の問題は、変数の数に関係なく排他性をチェックすることです。これは最初は機能と見なされるかもしれませんが、最初の問題は、変数の数が増えるにつれて (もしそうなら) はるかに重要になります。

于 2015-04-08T12:11:48.517 に答える
3

XOR は に実装されていoperator.xorます。

于 2012-01-09T11:49:00.883 に答える
0

Python が論理演算を処理する方法は混乱を招く可能性があるため、私の実装では、単純な True/False 回答のオプション (デフォルトで) をユーザーに提供します。実際の Python の結果は、オプションの 3 番目の引数を None に設定することで取得できます。

def xor(a, b, true=True, false=False): # set true to None to get actual Python result
    ab1 = a and not b
    ab2 = not a and b
    if bool(ab1) != bool(ab2):
        return (ab1 or ab2) if true is None else true
    else:
        return false
于 2020-12-15T01:02:42.460 に答える