2012-11-28 7 views
25

Sollte eine einfache Frage sein, aber ich kann nirgendwo eine Antwort finden. Der Operator ~ in Python ist als bitweiser Inversionsoperator dokumentiert. Fein. Ich habe zwar scheinbar schizophrene Verhalten bemerkt haben, nämlich:Python Tilde unärer Operator als Negation numpy Bool Array

~True -> -2 
~1 -> -2 
~False -> -1 
~0 -> -1 
~numpy.array([True,False],dtype=int) -> array([-2,-1]) 
~numpy.array([True,False],dtype=bool) -> array([False,True]) 

In den ersten vier Beispielen kann ich sehen, dass Python implementiert (wie dokumentiert) ~x = -(x+1), mit dem als int behandelt Eingang, auch wenn es boolean ist . Daher wird ~ für einen skalaren booleschen Wert nicht als logische Negation behandelt. Nicht, dass das Verhalten in einem numpy-Array, das mit booleschen Werten definiert ist, mit einem int-Typ identisch ist.

Warum funktioniert ~ dann als logische Negation Operator auf einem booleschen Array (Beachten Sie auch: ~numpy.isfinite(numpy.inf) -> True?)?

Es ist extrem ärgerlich, dass ich auf einem Skalar verwenden muss, aber not() wird nicht funktionieren, um ein Array zu negieren. Dann für ein Array, muss ich ~, verwenden aber ~ keinen Skalar negieren arbeiten ...

Antwort

26

not implementiert durch die __nonzero__ spezielle Methode, die erforderlich ist, zurückzukehren entweder True oder False, so kann es‘ t gebe das gewünschte Ergebnis. Stattdessen wird der Operator ~ verwendet, der durch die spezielle Methode __not__ implementiert wird. Aus dem gleichen Grund werden & und | anstelle von and und or verwendet.

PEP 335 zielte auf das Überladen von booleschen Operatoren zu, wurde aber wegen übermäßigem Overhead abgelehnt (es würde beispielsweise if Anweisungen komplizieren). PEP 225 schlägt eine allgemeine Syntax für "elementweise" Operatoren vor, die eine allgemeinere Lösung bieten würde, aber zurückgestellt wurde. Es scheint, dass die gegenwärtige Situation, obwohl sie umständlich ist, nicht schmerzhaft genug ist, um eine Veränderung zu erzwingen.

np.isfinite Wenn ein Skalar aufgerufen wird, wird ein Wert vom Typ np.bool_ zurückgegeben, nicht bool. np.bool_ ist auch der Typ, den Sie erhalten, wenn Sie einen Skalarwert aus einem Array von bool dtype extrahieren. Wenn Sie np.True_ und np.False_ anstelle von True und False verwenden, erhalten Sie konsistentes Verhalten unter ~.

+0

Danke ecatmur für die Erklärung und vor allem für die Erwähnung von '&' und '|'. Ich wusste nichts über diese und hatte stattdessen logic_and und logical_or verwendet. –

+0

Ich benutze 'numpy' seit Jahren und kannte bis jetzt nicht den Zweck dieser scheinbar neu definierten aber unterstrichenen Konstrukte wie' np.False_'. Das macht jetzt alles Sinn – dashesy