326 votes

L'opérateur tilde en Python

Quelle est l'utilisation de l'opérateur tilde en Python ?

Une chose à laquelle je pense est de faire quelque chose des deux côtés d'une chaîne ou d'une liste, comme vérifier si une chaîne est palindromique ou non :

def is_palindromic(s):
    return all(s[i] == s[~i] for i in range(len(s) / 2)) 

Un autre bon usage ?

22 votes

Notez que l'opérateur de complément unaire ~ mis en œuvre par la méthode spéciale __invert__ n'est pas liée à la not qui annule logiquement la valeur renvoyée par l'opérateur __bool__ (ou __nonzero__ en 2.x). Ce n'est pas non plus lié à la - opérateur de négation unaire, mis en œuvre par __neg__ . Par exemple ~True == -2 ce qui n'est pas le cas. False ou faux, et -False == 0 ce qui est toujours faux.

1 votes

@eryksun, bien que ce que vous avez dit soit juste ( -False==0 ) C'est déroutant, puisque vous parliez de la ~ y ~False == -1 ce qui n'est pas faux.

3 votes

@GuilhermedeLazari, le deuxième exemple était de comparer avec la négation arithmétique ( __neg__ ). J'aurais probablement dû continuer à utiliser True par exemple -True == -1 ce qui n'est pas -2 ou False ou faux, ce qui permet de le relier plus clairement à l' ~True et également que la négation arithmétique d'un bool est différente de sa négation logique. Je n'essayais pas d'être profond. Je mettais juste en évidence 3 opérations et les méthodes spéciales sous-jacentes qui sont parfois confondues.

292voto

wberry Points 6068

Il s'agit d'un opérateur unaire (prenant un seul argument) emprunté au C, où tous les types de données ne sont que des façons différentes d'interpréter les octets. C'est l'opération "inverser" ou "complémenter", dans laquelle tous les bits des données d'entrée sont inversés.

En Python, pour les entiers, les bits de l'élément représentation bi-complémentaire de l'entier sont inversés (comme dans b <- b XOR 1 pour chaque bit individuel), et le résultat est interprété à nouveau comme un entier complémentaire à deux. Donc pour les entiers, ~x est équivalent à (-x) - 1 .

La forme réifiée de la ~ est fourni en tant qu'opérateur operator.invert . Pour prendre en charge cet opérateur dans votre propre classe, donnez-lui un numéro d'identification de type __invert__(self) méthode.

>>> import operator
>>> class Foo:
...   def __invert__(self):
...     print 'invert'
...
>>> x = Foo()
>>> operator.invert(x)
invert
>>> ~x
invert

Toute classe dans laquelle il est utile d'avoir un "complément" ou un "inverse" d'une instance qui est également une instance de la même classe est un candidat possible pour l'opérateur d'inversion. Cependant, la surcharge d'opérateurs peut mener à la confusion si elle est mal utilisée, alors assurez-vous que cela a vraiment du sens avant de fournir un objet de type __invert__ à votre classe. (Notez que les chaînes d'octets [ex : '\xff' ] ne supportent pas cet opérateur, même s'il est significatif d'inverser tous les bits d'une chaîne d'octets).

156voto

GWW Points 20316

~ est le opérateur de complémentation binaire en python qui calcule essentiellement -x - 1

Ainsi, un tableau ressemblerait à

i  ~i
-----
0  -1
1  -2
2  -3
3  -4 
4  -5 
5  -6

Donc pour i = 0 elle comparerait s[0] con s[len(s) - 1] pour i = 1 , s[1] con s[len(s) - 2] .

En ce qui concerne votre autre question, cela peut être utile pour une série de trucs et astuces sur les bits .

42voto

Le Frite Points 462

Il faut noter que dans le cas de l'indexation des tableaux, array[~i] s'élève à reversed_array[i] . Cela peut être vu comme une indexation commençant à la fin du tableau :

[0, 1, 2, 3, 4, 5, 6, 7, 8]
    ^                 ^
    i                ~i

7 votes

C'est principalement parce que la valeur qui sort de ~i (c'est-à-dire une valeur négative) sert de point de départ pour l'index du tableau, ce que python accepte volontiers, ce qui a pour effet d'enrouler l'index et de le prélever à l'arrière.

38voto

Nicholas Points 891

En plus d'être un opérateur de complément au sens du bit, ~ peut également aider à inverser un boolean valeur, bien qu'il ne s'agisse pas de la convention bool ici, vous devez plutôt utiliser numpy.bool_ .


Ceci est expliqué dans,

import numpy as np
assert ~np.True_ == np.False_

L'inversion de la valeur logique peut parfois être utile, par exemple, ci-dessous ~ L'opérateur est utilisé pour nettoyer votre jeu de données et vous retourner une colonne sans NaN.

from numpy import NaN
import pandas as pd

matrix = pd.DataFrame([1,2,3,4,NaN], columns=['Number'], dtype='float64')
# Remove NaN in column 'Number'
matrix['Number'][~matrix['Number'].isnull()]

0 votes

numpy.NaN semble être défini comme numpy.float . Si j'essaie ~numpy.NaN , python se plaint que l'opérateur unaire ~ n'est pas définie pour le type numpy.float .

2 votes

@M.Herzkamp, c'est exact. NaN, +Inf, et -Inf sont des cas particuliers de nombres à virgule flottante. Inverser les bits d'un nombre à virgule flottante produirait un résultat absurde, donc Python ne le permet pas. C'est pourquoi vous devez d'abord appeler .isnull() ou np.isnan() sur votre tableau de données, puis inverser les valeurs booléennes résultantes.

16 votes

Notez, que ~True résulte en -2 tandis que pour les booléens numpy ~np.True_ résulte en False .

16voto

Adam Hughes Points 4177

La seule fois où je l'ai utilisé en pratique, c'est avec numpy/pandas . Par exemple, avec le .isin() méthode des cadres de données .

Dans les documents, ils montrent cet exemple de base

>>> df.isin([0, 2])
        num_legs  num_wings
falcon      True       True
dog        False       True

Mais si à la place vous vouliez que toutes les rangées pas dans [0, 2] ?

>>> ~df.isin([0, 2])
        num_legs  num_wings
falcon     False       False
dog        True        False

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X