Was macht der Caret-Operator (^) in Python?

111

Ich bin heute in Python auf den Caret-Operator gestoßen und habe beim Ausprobieren die folgende Ausgabe erhalten:

>>> 8^3
11
>>> 8^4
12
>>> 8^1
9
>>> 8^0
8
>>> 7^1
6
>>> 7^2
5
>>> 7^7
0
>>> 7^8
15
>>> 9^1
8
>>> 16^1
17
>>> 15^1
14
>>>

Es scheint auf 8 zu basieren, also vermute ich eine Art Byte-Operation? Ich kann anscheinend nicht viel über diese Suchseiten finden, außer dass sie sich für Floats merkwürdig verhalten. Hat jemand einen Link zu dem, was dieser Operator tut, oder können Sie es hier erklären?

Braten
quelle
4
Für ganze Zahlen das gleiche wie in C. ^ _-
Mike DeSimone
15
Zu help('^')
Ihrer Information
5
Beachten Sie, dass es sich bei Floats nicht ungewöhnlich verhält (bei Floats funktioniert es einfach nicht!). Beachten Sie auch, dass viele Menschen versehentlich auf diesen stoßen **, während sie nach dem Potenzierungsoperator suchen .
Mike Graham
3
@seth: help('^')macht nichts in meinem Python 2.6.1 (Apple Build). @ S.Lott: Meinst du das ( docs.python.org/reference/… ), wenn du "vollständig abgedeckt" sagst?. Scheint ein bisschen spärlich für jemanden, der mit dem Konzept nicht vertraut ist ...
ChristopheD
3
Vielen Dank an alle, ich denke, wenn ich gewusst hätte, dass es sich um einen bitweisen Operator handelt, hätte ich genau gewusst, wo ich suchen muss, aber ich habe es nicht getan, daher die Frage :) Vielen Dank an alle für Ihre Antworten, sie waren alle hilfreich und jetzt weiß ich ein bisschen mehr ! :)
Fry

Antworten:

173

Es ist ein bitweises XOR (exklusives ODER).

Es ergibt sich wahr, wenn einer (und nur einer) der Operanden wahr ist.

Demonstrieren:

>>> 0^0
0
>>> 1^1
0
>>> 1^0
1
>>> 0^1
1

Um eines Ihrer eigenen Beispiele zu erklären:

>>> 8^3
11

Denken Sie so darüber nach:

1000 # 8 (binär)
0011 # 3 (binär)
---- # XOR ANWENDEN ('vertikal')
1011 # result = 11 (binär)
ChristopheD
quelle
14
Ein etwas anschaulicheres Beispiel könnte sein, dass beide Zahlen 1dasselbe Bit haben, um dies zu verdeutlichen 1 xor 1 = 0.
Mike Graham
1
Ich wollte hinzufügen, dass Sie Binärzahlen erstellen können, indem Sie eingeben, 0bXwo X Ihre Binärzahl ist. 0b0001, 0b0010usw. Also, 0b1101 ^ 0b1110würde Ihnen 0b0011(oder 3) geben.
Jeff
Ich denke "Es ergibt sich als wahr, wenn einer (und nur einer) der Operanden (als) wahr bewertet." ist nicht genau, es wäre die Definition eines booleschen xor
Xavier Combelle
42

Es ruft nach Bedarf die Methode __xor__()oder __rxor__()des Objekts auf, die für ganzzahlige Typen ein bitweises Exklusiv-Oder ausführt.

Ignacio Vazquez-Abrams
quelle
4
+1, um darauf hinzuweisen, was es wirklich tut, außerhalb der Ganzzahloperation.
Mike DeSimone
8

Im Allgemeinen ist das Symbol ^eine Infix- Version der Methoden __xor__oder __rxor__. Unabhängig davon, welche Datentypen rechts und links vom Symbol platziert sind, muss diese Funktion auf kompatible Weise implementiert werden. Für Ganzzahlen ist dies die übliche XOROperation, aber zum Beispiel gibt es keine integrierte Definition der Funktion für Typ floatmit Typ int:

In [12]: 3 ^ 4
Out[12]: 7

In [13]: 3.3 ^ 4
---------------------------------------------------------------------------
TypeError                                 Traceback (most recent call last)
<ipython-input-13-858cc886783d> in <module>()
----> 1 3.3 ^ 4

TypeError: unsupported operand type(s) for ^: 'float' and 'int'

Eine nette Sache an Python ist, dass Sie dieses Verhalten in einer eigenen Klasse überschreiben können. In einigen Sprachen ^bedeutet das Symbol beispielsweise Exponentiation. Sie könnten dies auf diese Weise tun, nur als ein Beispiel:

class Foo(float):
    def __xor__(self, other):
        return self ** other

Dann wird so etwas funktionieren, und jetzt bedeutet das Symbol nur für Fälle vonFoo^ Potenzierung.

In [16]: x = Foo(3)

In [17]: x
Out[17]: 3.0

In [18]: x ^ 4
Out[18]: 81.0
ely
quelle
woah, war das überhaupt möglich? und könnten wir wahrscheinlich auch die Funktionsweise des +Operators ändern ?
K DawG
Ja, auf diese Weise kann das +Symbol eine Art von Aktion für list(Verkettung) ausführen, während eine andere Art von Aktion (mathematische Addition) für numerische Typen ausgeführt wird. In diesem Fall würden Sie die Methoden __add__oder __radd__in Ihrer Klasse überschreiben .
ely
1
Als Randnotiz wird die __r*__Version dieser (wie __rxor__oder __radd__) aus dem Argument auf der rechten Seite des Infix-Symbols aufgerufen , und zwar nur dann, wenn der Aufruf der Funktion für das linke Symbol nicht funktioniert. Sie können sich das so vorstellen try: left_hand_symbol.__xor__(right_hand_symbol); except: right_hand_symbol.__rxor__(left_hand_symbol), aber es xorkann durch einen der verfügbaren Infix-Operatoren im Python-Datenmodell ersetzt werden .
Ely
Das heißt, ich kann meinen eigenen Operator interstellen, der die Verkettung mit Zeichenfolgen ermöglicht? Mann, Python ist viel komplexer als ich dachte
K DawG
1
Man könnte also so etwas sagen (CompositionA | CompositionB) // CompositionCund es würde nur bedeuten "Komposition A spielen, gefolgt von Komposition B, während gleichzeitig parallel Komposition C spielen". Sprechen Sie über ein schönes Stück Code!
Ely
3

Wenn Sie den ^Operator verwenden, wird hinter den Vorhängen die Methode __xor__aufgerufen.

a^bist äquivalent zu a.__xor__(b).

Außerdem a ^= bentspricht a = a.__ixor__(b)(wobei __xor__als Ausweichlösung verwendet wird , wenn __ixor__implizit über Verwendung aufgerufen wird , ^=aber ist nicht vorhanden).

Grundsätzlich __xor__liegt es an der Umsetzung. Häufige Anwendungsfälle in Python sind:

  • Symmetrischer Unterschied von Mengen (alle Elemente in genau einer von zwei Mengen vorhanden)

Demo:

>>> a = {1, 2, 3}
>>> b = {1, 4, 5}
>>> a^b
{2, 3, 4, 5}
>>> a.symmetric_difference(b)
{2, 3, 4, 5}
  • Bitweise ungleich für die Bits von zwei ganzen Zahlen

Demo:

>>> a = 5
>>> b = 6
>>> a^b
3

Erläuterung:

    101 (5 decimal)
XOR 110 (6 decimal)
-------------------
    011 (3 decimal)
timgeb
quelle