Cosa fa l'operatore caret (^) in Python?


111

Oggi mi sono imbattuto nell'operatore caret in Python e provandolo, ho ottenuto il seguente output:

>>> 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
>>>

Sembra essere basato su 8, quindi immagino una sorta di operazione sui byte? Non riesco a trovare molto su questo sito di ricerca diverso da quello che si comporta in modo strano per i float, qualcuno ha un collegamento a ciò che fa questo operatore o puoi spiegarlo qui?


4
Per gli interi, la stessa cosa che fa in C. ^ _-
Mike DeSimone

15
Cordiali saluti, dalla shell python, puoi digitarehelp('^')
seth

6
Nota che non si comporta in modo strano per i float (semplicemente non funziona con i float!). Si noti inoltre che molte persone si imbattono accidentalmente in questo mentre cercano **l'operatore di esponenziazione.
Mike Graham

3
@seth: help('^')non fa nulla nel mio Python 2.6.1 (build apple). @ S.Lott: intendi questo ( docs.python.org/reference/… ) quando dici "completamente coperto" ?. Sembra un po 'scarso per qualcuno che non ha familiarità con il concetto ...
ChristopheD

3
Grazie a tutti, immagino che se avessi saputo che era un operatore bitwise avrei saputo dove cercare, ma non l'ho fatto, da qui la domanda :) Grazie a tutti per le vostre risposte sono stati tutti di aiuto e ora ne so un po 'di più ! :)
Venerdì

Risposte:


173

È uno XOR bit per bit (OR esclusivo).

Risulta vero se uno (e solo uno) degli operandi (restituisce) vero.

Dimostrare:

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

Per spiegare uno dei tuoi esempi:

>>> 8^3
11

Pensaci in questo modo:

1000 # 8 (binario)
0011 # 3 (binario)
---- # APPLICA XOR ('verticalmente')
1011 # risultato = 11 (binario)

14
Un esempio leggermente più illustrativo potrebbe includere entrambi i numeri che hanno 1lo stesso bit per renderlo chiaro 1 xor 1 = 0.
Mike Graham

1
Volevo aggiungere, puoi fare numeri binari digitando 0bXdove X è il tuo binario. 0b0001, 0b0010, Ecc Quindi, 0b1101 ^ 0b1110vi darebbe 0b0011(o 3).
Jeff

Penso "Risulta vero se uno (e solo uno) degli operandi (restituisce) vero". non è esatto, è quella che sarebbe la definizione di un xor booleano
Xavier Combelle

42

Richiama il metodo __xor__()or __rxor__()dell'oggetto secondo necessità, che per i tipi interi esegue un'esclusiva or bit per bit.


4
+1 per indicare cosa fa realmente , al di fuori dell'operazione con numeri interi.
Mike DeSimone


8

In generale, il simbolo ^è una versione infissa dei metodi __xor__o __rxor__. Qualunque tipo di dato sia posizionato a destra ea sinistra del simbolo deve implementare questa funzione in modo compatibile. Per gli interi, è l' XORoperazione comune , ma ad esempio non esiste una definizione incorporata della funzione per il tipo floatcon tipo 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'

Una cosa interessante di Python è che puoi sovrascrivere questo comportamento in una tua classe. Ad esempio, in alcune lingue il ^simbolo significa esponenziazione. Puoi farlo in questo modo, proprio come un esempio:

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

Poi qualcosa di simile a questo lavoro, e ora, per le istanze di Foosolo , la^ simbolo significherà elevamento a potenza.

In [16]: x = Foo(3)

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

In [18]: x ^ 4
Out[18]: 81.0

woah, era anche possibile? e potremmo forse cambiare anche il modo in cui funziona l' +operatore?
K DawG

Sì, è così che il +simbolo è in grado di eseguire un tipo di azione per list(concatenazione) mentre esegue un altro tipo di azione (addizione matematica) per i tipi numerici. In tal caso, sovrascriveresti i metodi __add__o __radd__nella tua classe.
ely

1
Come nota a margine, la __r*__versione di questi (come __rxor__o __radd__) verrà invocata dall'argomento che appare sul lato destro del simbolo infisso, e solo se la chiamata alla funzione per il simbolo della mano sinistra non funziona. Puoi pensarlo allo stesso modo try: left_hand_symbol.__xor__(right_hand_symbol); except: right_hand_symbol.__rxor__(left_hand_symbol), ma xorpuò essere sostituito da uno qualsiasi degli operatori infissi disponibili nel modello di dati Python .
ely

Quindi questo significa che posso creare il mio operatore che consente la intconcatenazione con le stringhe? amico, il pitone è molto complesso di quanto pensassi
K DawG

1
Quindi potresti dire qualcosa di simile (CompositionA | CompositionB) // CompositionCe significherebbe semplicemente "Suona la composizione A seguita dalla composizione B, nel frattempo suona anche la composizione C contemporaneamente in parallelo". Parla di un bel pezzo di codice!
ely

3

Quando usi l' ^operatore, dietro le quinte __xor__viene chiamato il metodo .

a^b è equivalente a a.__xor__(b) .

Inoltre, a ^= bè equivalente a a = a.__ixor__(b)(dove __xor__viene utilizzato come fallback quando __ixor__viene chiamato implicitamente tramite using^= ma non esiste).

In linea di principio, ciò che __xor__fa dipende completamente dalla sua attuazione. I casi d'uso comuni in Python sono:

  • Differenza simmetrica di insiemi (tutti gli elementi presenti esattamente in uno di due insiemi)

demo:

>>> a = {1, 2, 3}
>>> b = {1, 4, 5}
>>> a^b
{2, 3, 4, 5}
>>> a.symmetric_difference(b)
{2, 3, 4, 5}
  • Bitwise non uguale per i bit di due numeri interi

demo:

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

Spiegazione:

    101 (5 decimal)
XOR 110 (6 decimal)
-------------------
    011 (3 decimal)
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.