Что делает оператор каретки (^) в 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. ^ _-
Mike DeSimone

15
К вашему сведению, в оболочке python вы можете ввестиhelp('^')
сет,

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).
Джефф

Я думаю: «Это приводит к истине, если один (и только один) из операндов (оценивается как) истина».
неточно

42

При необходимости он вызывает метод объекта __xor__()or __rxor__(), который для целочисленных типов выполняет побитовое исключающее ИЛИ.


4
+1 за указание на то, что он действительно делает, помимо целочисленной операции.
Mike DeSimone


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

Ого, это вообще возможно? и можем ли мы, вероятно, изменить работу +оператора?
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объединять строки? чувак, питон намного сложнее, чем я думал
K DawG

1
Таким образом, вы можете сказать что-то вроде, (CompositionA | CompositionB) // CompositionCи это будет просто означать: «Воспроизвести композицию A, а затем композицию B, при этом одновременно воспроизводя композицию C параллельно». Поговорим о красивом фрагменте кода!
ely

3

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

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

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

В принципе, что __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.