Que fait l'opérateur caret (^) en Python?


111

J'ai rencontré l'opérateur caret en python aujourd'hui et je l'ai essayé, j'ai obtenu le résultat suivant:

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

Il semble être basé sur 8, donc je suppose une sorte d'opération d'octet? Je n'arrive pas à trouver grand chose à propos de ces sites de recherche à part qu'il se comporte étrangement pour les flotteurs, est-ce que quelqu'un a un lien vers ce que fait cet opérateur ou pouvez-vous l'expliquer ici?


4
Pour les entiers, la même chose est faite en C. ^ _-
— Mike DeSimone

15
Pour info, à partir du shell python, vous pouvez taperhelp('^')
— seth

6
Notez qu'il ne se comporte pas bizarrement pour les flottants (cela ne fonctionne tout simplement pas avec les flotteurs!). Notez également que de nombreuses personnes rencontrent accidentellement cela en recherchant **l'opérateur d'exponentiation.
— Mike Graham

3
@seth: help('^')ne fait rien dans mon Python 2.6.1 (version Apple). @ S.Lott: voulez-vous dire ceci ( docs.python.org/reference/… ) quand vous dites "complètement couvert" ?. Semble un peu rare pour quelqu'un qui ne connaît pas le concept ...
— ChristopheD

3
Merci à tous, je suppose que si j'avais su que c'était un opérateur au niveau du bit, j'aurais su exactement où chercher, mais je ne l'ai pas fait, d'où la question :) Merci à tous pour vos réponses, ils ont tous été utiles et maintenant j'en sais un peu plus ! :)
— Fry

Réponses:


173

C'est un XOR au niveau du bit (OU exclusif).

Il en résulte vrai si un (et un seul) des opérandes (est évalué à) vrai.

Démontrer:

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

Pour expliquer l'un de vos propres exemples:

>>> 8^3
11

Pensez-y de cette façon:

1000 # 8 (binaire)
0011 # 3 (binaire)
---- # APPLY XOR ('verticalement')
1011 # résultat = 11 (binaire)

14
Un exemple un peu plus illustratif pourrait inclure les deux nombres ayant 1dans le même bit pour le préciser 1 xor 1 = 0.
— Mike Graham

1
Je voulais ajouter, vous pouvez faire des nombres binaires en tapant 0bXoù X est votre binaire. 0b0001, 0b0010Etc. Alors, 0b1101 ^ 0b1110voulez - vous donner 0b0011(ou 3).
— Jeff

Je pense que "Il en résulte vrai si un (et un seul) des opérandes (évalue à) vrai." n'est pas exact, ce serait la définition d'un xor booléen
— Xavier Combelle

42

Il invoque la méthode __xor__()ou __rxor__()de l'objet si nécessaire, ce qui pour les types entiers effectue un ou exclusif au niveau du bit.


4
+1 pour avoir souligné ce qu'il fait vraiment , en dehors de l'opération entière.
— Mike DeSimone


8

De manière générale, le symbole ^est une version infixe des méthodes __xor__ou __rxor__. Quels que soient les types de données placés à droite et à gauche du symbole, ils doivent implémenter cette fonction de manière compatible. Pour les entiers, c'est l' XORopération courante , mais par exemple, il n'y a pas de définition intégrée de la fonction pour le type floatavec type 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'

Une chose intéressante à propos de Python est que vous pouvez remplacer ce comportement dans une classe de votre choix. Par exemple, dans certaines langues, le ^symbole signifie exponentiation. Vous pouvez le faire de cette façon, à titre d'exemple:

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

Ensuite, quelque chose comme ça fonctionnera, et maintenant, pour les instances de Fooseulement , le ^symbole signifiera l'exponentiation.

In [16]: x = Foo(3)

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

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

woah, était-ce même possible? et pourrions-nous probablement changer le fonctionnement de l' +opérateur aussi?
— K DawG

Oui, c'est ainsi que le +symbole est capable de faire un type d'action pour list(concaténation) tout en faisant un autre type d'action (addition mathématique) pour les types numériques. Dans ce cas, vous remplaceriez les méthodes __add__ou __radd__de votre classe.
— ely

1
En remarque, la __r*__version de ceux-ci (comme __rxor__ou __radd__) sera invoquée à partir de l'argument apparaissant sur le côté droit du symbole infixe, et seulement si l'appel à la fonction pour le symbole de gauche ne fonctionne pas. Vous pouvez penser à cela comme try: left_hand_symbol.__xor__(right_hand_symbol); except: right_hand_symbol.__rxor__(left_hand_symbol), mais xorpeut être remplacé par l'un des opérateurs d'infixe disponibles dans le modèle de données Python .
— ely

Cela signifie que je peux créer mon propre opérateur qui permet la intconcaténation avec des chaînes? mec, python est bien complexe que je ne le pensais
— K DawG

1
Vous pourriez donc dire quelque chose comme (CompositionA | CompositionB) // CompositionCet cela signifierait simplement "Jouez la composition A suivie de la composition B, en même temps, jouez également la composition C en même temps en parallèle". Parlez d'un beau morceau de code!
— ely

3

Lorsque vous utilisez l' ^opérateur, derrière les rideaux, la méthode __xor__est appelée.

a^béquivaut à a.__xor__(b).

Également, a ^= béquivaut à a = a.__ixor__(b)(où __xor__est utilisé comme solution de secours lorsque __ixor__est implicitement appelé via using ^=mais n'existe pas).

En principe, ce que __xor__fait dépend entièrement de sa mise en œuvre. Les cas d'utilisation courants en Python sont:

  • Différence symétrique des ensembles (tous les éléments présents dans exactement l'un des deux ensembles)

Démo:

>>> 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 pour les bits de deux entiers

Démo:

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

Explication:

    101 (5 decimal)
XOR 110 (6 decimal)
-------------------
    011 (3 decimal)
En utilisant notre site, vous reconnaissez avoir lu et compris notre politique liée aux cookies et notre politique de confidentialité.
Licensed under cc by-sa 3.0 with attribution required.