Apa yang dilakukan operator tanda sisipan (^) dengan Python?

111

Saya berlari melintasi operator caret dengan python hari ini dan mencobanya, saya mendapatkan output berikut:

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

Tampaknya didasarkan pada 8, jadi saya menebak semacam operasi byte? Saya tidak dapat menemukan banyak tentang situs pencarian ini selain berperilaku aneh untuk float, apakah ada yang memiliki link ke apa yang dilakukan operator ini atau dapatkah Anda menjelaskannya di sini?

Menggoreng
sumber
4
Untuk bilangan bulat, hal yang sama terjadi di C. ^ _-
Mike DeSimone
15
FYI, dari shell python, Anda dapat mengetikhelp('^')
seth
6
Perhatikan bahwa itu tidak berperilaku aneh untuk pelampung (hanya tidak bekerja dengan pelampung!). Perhatikan juga bahwa banyak orang secara tidak sengaja mengalami ini saat mencari **, operator eksponen.
Mike Graham
3
@ seth: help('^')tidak melakukan apa pun dalam Python 2.6.1 saya (build apel). @ S.Lott: maksud Anda ini ( docs.python.org/reference/… ) saat Anda mengatakan "sepenuhnya tertutup" ?. Tampaknya agak jarang bagi seseorang yang tidak terbiasa dengan konsep ...
ChristopheD
3
Terima kasih semuanya, saya kira jika saya tahu itu adalah operator yang bijak, saya akan tahu di mana harus mencari, tetapi saya tidak melakukannya, maka pertanyaannya :) Terima kasih semua atas jawaban Anda, mereka masing-masing membantu dan sekarang saya tahu sedikit lebih banyak ! :)
Goreng

Jawaban:

173

Ini XOR bitwise (eksklusif OR).

Hasilnya benar jika satu (dan hanya satu) dari operan (dievaluasi menjadi) benar.

Untuk menunjukkan:

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

Untuk menjelaskan salah satu contoh Anda sendiri:

>>> 8^3
11

Pikirkan seperti ini:

1000 # 8 (biner)
0011 # 3 (biner)
---- # APPLY XOR ('vertikal')
1011 # result = 11 (biner)
ChristopheD
sumber
14
Contoh yang lebih ilustratif mungkin mencakup kedua angka yang memiliki 1bit yang sama untuk memperjelasnya 1 xor 1 = 0.
Mike Graham
1
Saya ingin menambahkan, Anda dapat melakukan bilangan biner dengan mengetik di 0bXmana X adalah biner Anda. 0b0001,, 0b0010dll. Jadi, 0b1101 ^ 0b1110akan memberi Anda 0b0011(atau 3).
Jeff
Saya pikir "Ini menghasilkan true jika satu (dan hanya satu) operand (dievaluasi menjadi) benar." tidak tepat, itu yang akan menjadi definisi dari boolean xor
Xavier Combelle
42

Ini memanggil metode __xor__()atau __rxor__()dari objek sesuai kebutuhan, yang untuk tipe integer melakukan eksklusif-or.

Ignacio Vazquez-Abrams
sumber
4
1 untuk menunjukkan apa yang sebenarnya dilakukannya, di luar operasi integer.
Mike DeSimone
8

Secara umum, simbol ^adalah versi infix dari __xor__atau __rxor__metode. Tipe data apa pun yang ditempatkan di kanan dan kiri simbol harus mengimplementasikan fungsi ini dengan cara yang kompatibel. Untuk bilangan bulat, ini adalah XORoperasi umum , tetapi misalnya tidak ada definisi built-in dari fungsi untuk tipe floatdengan tipe 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'

Satu hal menarik tentang Python adalah Anda dapat mengganti perilaku ini di kelas Anda sendiri. Misalnya, dalam beberapa bahasa, ^simbol itu berarti eksponen. Anda dapat melakukannya dengan cara ini, hanya sebagai satu contoh:

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

Kemudian sesuatu seperti ini akan berhasil, dan sekarang, untuk contoh Foosaja , ^simbol itu berarti eksponen.

In [16]: x = Foo(3)

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

In [18]: x ^ 4
Out[18]: 81.0
ely
sumber
woah, apakah itu mungkin? dan bisakah kita mengubah cara kerja +operator juga?
K DawG
Ya, ini adalah cara +simbol dapat melakukan satu jenis tindakan untuk list(penggabungan) sambil melakukan jenis tindakan lain (penambahan matematis) untuk jenis numerik. Jika demikian, Anda akan mengganti metode __add__atau __radd__di kelas Anda.
ely
1
Sebagai catatan tambahan, __r*__versi ini (suka __rxor__atau __radd__) akan dipanggil dari argumen yang muncul di sisi kanan simbol infiks, dan hanya jika panggilan ke fungsi simbol tangan kiri tidak berfungsi. Anda dapat menganggapnya seperti itu try: left_hand_symbol.__xor__(right_hand_symbol); except: right_hand_symbol.__rxor__(left_hand_symbol), tetapi xordapat diganti dengan salah satu operator infix yang tersedia dalam Model Data Python .
ely
Jadi itu berarti saya bisa membuat operator saya sendiri yang memungkinkan intpenggabungan dengan string? Bung, python jauh lebih kompleks dari yang saya kira
K DawG
1
Jadi Anda bisa mengatakan sesuatu seperti (CompositionA | CompositionB) // CompositionCdan itu hanya berarti "Mainkan komposisi A diikuti oleh komposisi B, sementara itu juga memainkan komposisi C pada saat yang sama secara paralel." Bicara tentang sepotong kode yang indah!
ely
3

Saat Anda menggunakan ^operator, di balik tirai __xor__disebut metode .

a^bsetara dengan a.__xor__(b).

Juga, a ^= bsetara dengan a = a.__ixor__(b)(di mana __xor__digunakan sebagai fallback ketika __ixor__secara implisit dipanggil melalui using ^=tapi tidak ada).

Pada prinsipnya apa yang __xor__dilakukan sepenuhnya terserah implementasinya. Kasus penggunaan umum di Python adalah:

  • Perbedaan Symmetric dari himpunan (semua elemen ada tepat di salah satu dari dua himpunan)

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-Equal untuk bit dari dua bilangan bulat

Demo:

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

Penjelasan:

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