Ich bin auf einen Code mit einer ähnlichen Zeile gestoßen
x[x<2]=0
Ich spiele mit Variationen herum und bin immer noch fest davon überzeugt, was diese Syntax bewirkt.
Beispiele:
>>> x = [1,2,3,4,5]
>>> x[x<2]
1
>>> x[x<3]
1
>>> x[x>2]
2
>>> x[x<2]=0
>>> x
[0, 2, 3, 4, 5]
python
python-2.7
numpy
aberger
quelle
quelle
TypeError: unorderable types: list() < int()
.Antworten:
Dies ist nur bei NumPy- Arrays sinnvoll . Das Verhalten mit Listen ist nutzlos und spezifisch für Python 2 (nicht Python 3). Möglicherweise möchten Sie überprüfen, ob das ursprüngliche Objekt tatsächlich ein NumPy-Array (siehe weiter unten) und keine Liste war.
Aber in Ihrem Code hier ist x eine einfache Liste.
Schon seit
ist also falsch, dh 0
x[x<2]
istx[0]
x[0]
wird geändert.Umgekehrt
x[x>2]
istx[True]
oderx[1]
Also
x[1]
wird geändert.Warum passiert das?
Die Vergleichsregeln sind:
Wenn Sie zwei Zeichenfolgen oder zwei numerische Typen bestellen, erfolgt die Reihenfolge wie erwartet (lexikografische Reihenfolge für Zeichenfolge, numerische Reihenfolge für Ganzzahlen).
Wenn Sie einen numerischen und einen nicht numerischen Typ bestellen, steht der numerische Typ an erster Stelle.
Wenn Sie zwei inkompatible Typen bestellen, bei denen keiner numerisch ist, werden sie nach der alphabetischen Reihenfolge ihrer Typnamen sortiert:
Wir haben also die folgende Reihenfolge
numerisch <Liste <Zeichenfolge <Tupel
Siehe die akzeptierte Antwort für Wie vergleicht Python String und Int? .
Wenn x ein NumPy-Array ist , ist die Syntax aufgrund der Booleschen Array-Indizierung sinnvoller . In diesem Fall
x < 2
ist das überhaupt kein Boolescher Wert. Es ist ein Array von Booleschen Werten, die darstellen, ob jedes Elementx
kleiner als 2 war.x[x < 2] = 0
Anschließend werden die Elemente ausgewähltx
, die kleiner als 2 waren, und diese Zellen werden auf 0 gesetzt. Siehe Indizierung .quelle
import
Ich werde mit ziemlicher Sicherheit eine für numpy sehen.[0 if i < 2 else i for i in x]
.) Oder ist dieser Stil in Numpy ermutigt?x[x<2]
gibt ein numpy-Array zurück, während[0 if i<2 else i for i in x]
eine Liste zurückgegeben wird. Dies liegt daran, dassx[x<2]
es sich um eine Indizierungsoperation handelt (in numpy / scipy / pandas aufgrund der Fähigkeit, Daten zu maskieren, als Slicing-Operation bezeichnet), während das Listenverständnis eine neue Objektdefinition ist. Siehe NumPy-IndizierungDer Bool wird einfach in eine Ganzzahl konvertiert. Der Index ist entweder 0 oder 1.
quelle
x
und2
sind „ bestellt konsequent aber willkürlich “ und dass die Reihenfolge in verschiedenen Python - Implementierungen ändern könnte.x<2 == false
?bool
wird nicht in eine Ganzzahl konvertiert, einebool
in Python ist eine Ganzzahlbool
ist eine Unterklasse vonint
.Der ursprüngliche Code in Ihrer Frage kann nur in Python 2. Wenn
x
alist
2 in Python, der Vergleichx < y
ist ,False
wenny
ein istint
eger. Dies liegt daran, dass es nicht sinnvoll ist, eine Liste mit einer Ganzzahl zu vergleichen. Wenn die Operanden in Python 2 nicht vergleichbar sind, basiert der Vergleich in CPython auf der alphabetischen Reihenfolge der Namen der Typen . Außerdem stehen bei gemischten Vergleichen alle Zahlen an erster Stelle . Dies wird in der Dokumentation von CPython 2 nicht einmal beschrieben, und verschiedene Python 2-Implementierungen können zu unterschiedlichen Ergebnissen führen. Das wird[1, 2, 3, 4, 5] < 2
ausgewertet,False
weil2
eine Zahl und damit "kleiner" als einelist
in CPython ist. Dieser gemischte Vergleich war schließlichwird als zu undurchsichtig angesehen und in Python 3.0 entfernt.Das Ergebnis von
<
ist abool
; undbool
ist eine Unterklasse vonint
:Sie nehmen also im Grunde das Element 0 oder 1, je nachdem, ob der Vergleich wahr oder falsch ist.
Wenn Sie den obigen Code in Python 3 ausprobieren, erhalten Sie
TypeError: unorderable types: list() < int()
aufgrund einer Änderung in Python 3.0 :Es gibt viele Datentypen, die die Vergleichsoperatoren überladen , um etwas anderes zu tun (Datenrahmen von Pandas, Numpys Arrays). Wenn der von Ihnen verwendete Code etwas anderes getan hat, lag dies daran, dass
x
es sich nicht um einelist
Instanz einer anderen Klasse handelte, deren Operator<
überschrieben wurde, um einen Wert zurückzugeben, der kein a istbool
. und dieser Wert wurde dann speziell vonx[]
(aka__getitem__
/__setitem__
) behandeltquelle
+False
Hallo Perl, hey JavaScript, wie geht es euch?UNARY_POSITIVE
Opcode, der die__pos__
__setitem__
statt__getitem__
in deinem letzten Abschnitt. Ich hoffe auch, dass es Ihnen nichts ausmacht, dass meine Antwort von diesem Teil Ihrer Antwort inspiriert wurde.__getitem__
obwohl es genauso hätte sein können__setitem__
und__delitem__
Dies hat noch eine weitere Verwendung: Code Golf. Code Golf ist die Kunst, Programme zu schreiben, die ein Problem in möglichst wenigen Quellcode-Bytes lösen.
ist ungefähr gleichbedeutend mit
außer dass sowohl a als auch b in der ersten Version ausgewertet werden, nicht jedoch in der zweiten Version.
c<d
bewertet zuTrue
oderFalse
.(a, b)
ist ein Tupel.Die Indizierung für ein Tupel funktioniert wie die Indizierung für eine Liste:
(3,5)[1]
==5
.True
ist gleich1
undFalse
ist gleich0
.(a,b)[c<d]
(a,b)[True]
(a,b)[1]
b
oder für
False
:(a,b)[c<d]
(a,b)[False]
(a,b)[0]
a
Es gibt eine gute Liste im Stack-Exchange-Netzwerk mit vielen fiesen Dingen, die Sie mit Python tun können, um ein paar Bytes zu sparen. /codegolf/54/tips-for-golfing-in-python
Obwohl dies im normalen Code niemals verwendet werden sollte, würde dies in Ihrem Fall bedeuten, dass es
x
sowohl als etwas fungiert, das mit einer Ganzzahl verglichen werden kann, als auch als ein Container, der das Schneiden unterstützt, was eine sehr ungewöhnliche Kombination ist. Es ist wahrscheinlich Numpy-Code, wie andere betont haben.quelle
Code Golf is the art of writing programs
: ')Im Allgemeinen könnte es alles bedeuten . Es war bereits erklärt , was es bedeutet , wenn
x
eine istlist
odernumpy.ndarray
aber im Allgemeinen es hängt nur davon ab , wie die Vergleichsoperator (<
,>
, ...) und auch , wie das get / set-item ([...]
-Syntax) implementiert.Weil:
x < value
ist äquivalent zux.__lt__(value)
x[value]
ist (ungefähr) äquivalent zux.__getitem__(value)
x[value] = othervalue
ist (auch ungefähr) äquivalent zux.__setitem__(value, othervalue)
.Dies kann angepasst werden, um alles zu tun, was Sie wollen. Nur als Beispiel (ahmt eine etwas numpys-boolesche Indizierung nach):
Nun wollen wir sehen, was passiert, wenn Sie es verwenden:
Beachten Sie, dass dies nur eine Möglichkeit ist. Sie können fast alles implementieren, was Sie wollen.
quelle