Co robi operator karetki (^) w Pythonie?

111

Natknąłem się dziś na operatora karetki w Pythonie i wypróbowując go, otrzymałem następujący wynik:

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

Wydaje się, że jest oparty na 8, więc zgaduję, że jest to operacja na bajtach? Wydaje się, że nie mogę znaleźć zbyt wiele informacji na temat tych witryn wyszukiwania, poza tym, że zachowuje się dziwnie w przypadku pływaków, czy ktoś ma link do tego, co robi ten operator, czy możesz to tutaj wyjaśnić?

Smażyć
źródło
4
W przypadku liczb całkowitych to samo dzieje się w C. ^ _-
Mike DeSimone
15
FYI, z powłoki Pythona, możesz wpisaćhelp('^')
seth
6
Zauważ, że nie zachowuje się dziwnie dla pływaków (po prostu nie działa z pływakami!). Zauważ również, że wiele osób przypadkowo wpada na to, szukając **operatora potęgowania.
Mike Graham
3
@seth: help('^')nic nie robi w moim Pythonie 2.6.1 (kompilacja Apple). @ S.Lott: czy masz na myśli to ( docs.python.org/reference/… ), kiedy mówisz „całkowicie zakryte” ?. Wydaje się trochę rzadkie dla kogoś, kto nie jest zaznajomiony z tą koncepcją ...
ChristopheD
3
Dzięki wszystkim, myślę, że gdybym wiedział, że to operator bitowy, wiedziałbym dokładnie, gdzie szukać, ale nie wiedziałem, stąd pytanie :) Dziękuję wszystkim za twoje odpowiedzi, każdy był pomocny i teraz wiem trochę więcej ! :)
Smaż

Odpowiedzi:

173

To bitowe XOR (ekskluzywne OR).

Daje wynik true, jeśli jeden (i tylko jeden) z operandów (przyjmuje wartość) true.

Aby zademonstrować:

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

Aby wyjaśnić jeden z własnych przykładów:

>>> 8^3
11

Pomyśl o tym w ten sposób:

1000 # 8 (binarne)
0011 # 3 (binarne)
---- # ZASTOSUJ XOR („pionowo”)
1011 # wynik = 11 (binarny)
ChristopheD
źródło
14
Nieco bardziej obrazowy przykład może obejmować obie liczby 1w tym samym bicie, aby to wyjaśnić 1 xor 1 = 0.
Mike Graham
1
Chciałem dodać, że możesz robić liczby binarne, wpisując 0bXgdzie X jest twoim binarnym. 0b0001, 0b0010itp. Więc 0b1101 ^ 0b1110dałby ci 0b0011(lub 3).
Jeff,
Myślę, że „Wynikiem tego jest prawda, jeśli jeden (i tylko jeden) z operandów (przyjmuje wartość) prawda”. nie jest dokładne, to jaka byłaby definicja boolowskiego xora
Xavier Combelle
42

W razie potrzeby wywołuje metodę __xor__()lub __rxor__()obiektu, co w przypadku typów całkowitych wykonuje bitowe wyłączanie lub.

Ignacio Vazquez-Abrams
źródło
4
+1 za wskazanie, co naprawdę robi, poza operacją na liczbach całkowitych.
Mike DeSimone
8

Ogólnie rzecz biorąc, symbol ^jest wersją wrostkową metod __xor__lub __rxor__. Jakiekolwiek typy danych są umieszczone po prawej i lewej stronie symbolu, muszą implementować tę funkcję w kompatybilny sposób. W przypadku liczb całkowitych jest to typowa XORoperacja, ale na przykład nie ma wbudowanej definicji funkcji dla typu floatz typem 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'

Jedną fajną rzeczą w Pythonie jest to, że możesz nadpisać to zachowanie w swojej własnej klasie. Na przykład w niektórych językach ^symbol oznacza potęgowanie. Możesz to zrobić w ten sposób, na przykład:

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

Potem coś jak to będzie działać, a teraz do wystąpień Footylko The ^symbol oznacza potęgowanie.

In [16]: x = Foo(3)

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

In [18]: x ^ 4
Out[18]: 81.0
ely
źródło
woah, czy to w ogóle możliwe? i czy moglibyśmy prawdopodobnie zmienić sposób działania +operatora?
K DawG
Tak, w ten sposób +symbol może wykonać jedną akcję dla list(konkatenację), podczas gdy inny rodzaj akcji (dodawanie matematyczne) dla typów liczbowych. W takim przypadku zastąpiłbyś metody __add__lub __radd__w swojej klasie.
ely
1
Na marginesie, __r*__wersja tych (like __rxor__or __radd__) zostanie wywołana z argumentu pojawiającego się po prawej stronie symbolu wrostka i tylko wtedy, gdy wywołanie funkcji dla symbolu lewej ręki nie działa. Możesz o tym myśleć w ten sposób try: left_hand_symbol.__xor__(right_hand_symbol); except: right_hand_symbol.__rxor__(left_hand_symbol), ale xormożna to zastąpić dowolnym z dostępnych operatorów wrostków w modelu danych Pythona .
ely
Oznacza to, że mogę stworzyć własnego operatora, który pozwala na intkonkatenację z ciągami znaków? człowieku, Python jest o wiele bardziej złożony niż myślałem
K DawG
1
Możesz więc powiedzieć coś w stylu, (CompositionA | CompositionB) // CompositionCco oznaczałoby po prostu „Odtwórz kompozycję A, a następnie kompozycję B, w międzyczasie grając jednocześnie kompozycję C w tym samym czasie”. Porozmawiaj o pięknym fragmencie kodu!
ely
3

Kiedy używasz ^operatora, za zasłonami __xor__wywoływana jest metoda .

a^b jest równa a.__xor__(b) .

Ponadto a ^= bjest równoważne z a = a.__ixor__(b)(gdzie __xor__jest używane jako rezerwowe, gdy __ixor__jest niejawnie wywoływane za pośrednictwem using^= ale nie istnieje).

W zasadzie to, co się __xor__dzieje, zależy całkowicie od jego wdrożenia. Typowe przypadki użycia w Pythonie to:

  • Symetryczna różnica zbiorów (wszystkie elementy występują dokładnie w jednym z dwóch zestawów)

Próbny:

>>> a = {1, 2, 3}
>>> b = {1, 4, 5}
>>> a^b
{2, 3, 4, 5}
>>> a.symmetric_difference(b)
{2, 3, 4, 5}
  • Bitowo nie równe dla bitów dwóch liczb całkowitych

Próbny:

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

Wyjaśnienie:

    101 (5 decimal)
XOR 110 (6 decimal)
-------------------
    011 (3 decimal)
timgeb
źródło