Що робить оператор caret (^) в Python?


111

Я сьогодні наткнувся на оператора карети в python і спробувавши це, я отримав такий результат:

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

Здається, це базується на 8, тому я здогадуюсь про якусь байтну операцію? Мені здається, я не знаю багато про ці пошукові сайти, крім того, що він дивно поводиться з плаваючими, чи хтось має посилання на те, що робить цей оператор, чи ви можете це пояснити тут?


4
Для цілих чисел те саме робиться у C. ^ _-
Майк Десимоне,

15
FYI, з оболонки пітона, ви можете набратиhelp('^')
seth

6
Зауважте, що він не поводиться дивно для поплавців (просто не працює з поплавками!). Також зауважте, що багато людей випадково натрапляють на це під час пошуку **оператора експоненції.
Майк Грехем

3
@seth: help('^')нічого в моєму Python 2.6.1 (яблучна збірка) не робить. @ S.Lott: ти це маєш на увазі ( docs.python.org/reference/… ), коли ти кажеш "повністю охоплений" ?. Здається трохи рідко для того, хто незнайомий із концепцією ...
ChristopheD

3
Дякую всім, я гадаю, якби я знав, що це бітовий оператор, я би знав правильно, де шукати, але я цього не зробив, звідси питання :) Дякую всім за ваші відповіді, вони були корисними, і тепер я знаю трохи більше ! :)
Смажиться

Відповіді:


173

Це побіт XOR (виключно АБО).

Це приводить до істини, якщо один (і лише один) з операндів (оцінює до) істинним.

Демонструвати:

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

Щоб пояснити один із власних прикладів:

>>> 8^3
11

Подумайте про це так:

1000 # 8 (двійковий)
0011 №3 (двійковий)
---- # ЗАСТОСИТИ XOR ("вертикально")
1011 # результат = 11 (двійковий)

14
Трохи більш наочний приклад може включати обидва числа, що мають один і 1той же біт, щоб зрозуміти це 1 xor 1 = 0.
Майк Грехем

1
Я хотів додати, ви можете робити двійкові числа, ввівши, 0bXде X - ваш двійковий. 0b0001, 0b0010і т. д. Отже, 0b1101 ^ 0b1110дамо вам 0b0011(або 3).
Джефф

Я думаю, що "це призводить до істини, якщо один (і тільки один) з операндів (оцінюється до)". не точно, це було б визначення булевого xor
Xavier Combelle

42

Він викликає __xor__()або __rxor__()метод об'єкта за потребою, який для цілих типів робить побітовим ексклюзивним або.


4
+1 для вказівки на те, що це насправді , поза цілочисельною операцією.
Майк Десімоне


8

Взагалі кажучи, символ ^є інфікованою версією методів __xor__або __rxor__. Незалежно від типів даних, розміщених праворуч і ліворуч від символу, він повинен реалізувати цю функцію сумісно. Для цілих чисел це звичайна XORоперація, але, наприклад, немає вбудованого визначення функції для типу floatз типом 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'

Один з акуратних речей щодо Python - це те, що ви можете переохотити таку поведінку у власному класі. Наприклад, у деяких мовах ^символ означає експоненцію. Ви можете зробити це так, як один із прикладів:

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

Потім що - то , як це буде працювати, і тепер, за винятком випадків Fooтільки , то ^символ означатиме зведення в ступінь.

In [16]: x = Foo(3)

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

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

woah, це було можливо навіть? і чи могли ми, можливо, змінити, як +працює оператор?
K DawG

Так, саме такий +символ здатний робити один вид дії list(конкатенація), виконуючи інший вид дій (математичне додавання) для числових типів. У такому випадку ви б перекрили __add__або __radd__методи у своєму класі.
ely

1
В якості бічної примітки, __r*__версія цього (наприклад, __rxor__або __radd__) буде викликана з аргументу, що з’являється з правого боку символу інфіксації, і лише якщо виклик функції для символу лівої руки не працює. Ви можете думати про це як try: left_hand_symbol.__xor__(right_hand_symbol); except: right_hand_symbol.__rxor__(left_hand_symbol), але xorйого можна замінити будь-яким із доступних операторів інфікування у моделі даних Python .
ely

Отже, це означає, що я можу створити власного оператора, який дозволяє intоб'єднувати рядки? man, python - це складний спосіб, ніж я думав
K DawG

1
Отже, ви можете сказати щось на кшталт, (CompositionA | CompositionB) // CompositionCі це просто означало б "Грати композицію А, а потім композицію В, а також паралельно грати композицію C". Поговоримо про гарний фрагмент коду!
ely

3

Коли ви використовуєте ^оператор, за шторами __xor__називається метод .

a^bеквівалентно a.__xor__(b).

Крім того, a ^= bвін еквівалентний a = a.__ixor__(b)(де __xor__використовується як резервна копія, коли __ixor__неявно викликається через використання, ^=але не існує).

В принципі, те, що __xor__робить, повністю залежить від його реалізації. Поширені випадки використання в Python:

  • Симетрична різниця множин (всі елементи присутні саме в одному з двох наборів)

Демонстрація:

>>> a = {1, 2, 3}
>>> b = {1, 4, 5}
>>> a^b
{2, 3, 4, 5}
>>> a.symmetric_difference(b)
{2, 3, 4, 5}
  • Побітові нерівні для бітів двох цілих чисел

Демонстрація:

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

Пояснення:

    101 (5 decimal)
XOR 110 (6 decimal)
-------------------
    011 (3 decimal)
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.