Ich kann nicht verstehen, warum Python keine sign
Funktion hat. Es hat ein abs
eingebautes (was ich als sign
Schwester betrachte), aber neinsign
.
In Python 2.6 gibt es sogar eine copysign
Funktion (in Mathe ), aber kein Vorzeichen. Warum sich die Mühe machen, eine zu schreiben, copysign(x,y)
wenn man einfach eine schreiben sign
und dann die copysign
direkt von bekommen könnte abs(x) * sign(y)
? Letzteres wäre viel klarer: x mit dem Vorzeichen von y, während Sie beim Copysign daran denken müssen, ob es x mit dem Vorzeichen von y oder y mit dem Vorzeichen von x ist!
Offensichtlich sign(x)
bietet nichts mehr alscmp(x,0)
, aber es wäre viel besser lesbar als dies (und für eine gut lesbare Sprache wie Python wäre dies ein großes Plus gewesen).
Wenn ich ein Python-Designer wäre, wäre ich umgekehrt: kein cmp
eingebauter, aber ein sign
. Wenn Sie brauchen cmp(x,y)
, können Sie einfach ein sign(x-y)
(oder, noch besser für nicht numerische Dinge, nur ein x> y - natürlich hätte dies das sorted
Akzeptieren eines Booleschen Wertes anstelle eines ganzzahligen Komparators erfordern müssen ). Dies wäre auch klar: positiv , wenn x>y
(während bei cmp
Ihnen müssen die Konvention positiv erinnern , als der erste ist größer , aber es könnte umgekehrt sein). Natürlichcmp
macht es aus anderen Gründen Sinn (z. B. beim Sortieren nicht numerischer Dinge oder wenn Sie möchten, dass die Sortierung stabil ist, was mit einem einfachen Booleschen Wert nicht möglich ist).
Die Frage ist also: Warum haben die Python-Designer beschlossen, die sign
Funktion aus der Sprache herauszulassen? Warum zum Teufel mit copysign
und nicht mit seinen Eltern ?sign
?
Vermisse ich etwas
EDIT - nach Peter Hansen Kommentar. Fair genug, dass Sie es nicht benutzt haben, aber Sie haben nicht gesagt, wofür Sie Python verwenden. In 7 Jahren, in denen ich Python benutze, brauchte ich es unzählige Male, und der letzte ist der Strohhalm, der dem Kamel den Rücken gebrochen hat!
Ja, Sie können cmp weitergeben, aber 90% der Fälle, in denen ich es weitergeben musste, waren in einer solchen Sprache
lambda x,y: cmp(score(x),score(y))
, die mit sign gut funktioniert hätte.
Schließlich hoffe ich, dass Sie zustimmen, dass sign
dies nützlicher wäre als copysign
. Selbst wenn ich Ihre Ansicht gekauft hätte, warum sollten Sie sich die Mühe machen, dies in Mathematik zu definieren, anstatt zu unterschreiben? Wie kann Copysign so nützlich sein als Sign?
quelle
Antworten:
BEARBEITEN:
In der Tat gab es einen Patch, der
sign()
in Mathe enthalten war , aber er wurde nicht akzeptiert, weil sie sich nicht einig waren, was er in allen Randfällen zurückgeben sollte (+/- 0, +/- nan usw.) zurückgegeben werden sollte.Daher haben sie beschlossen, nur Copysign zu implementieren, das (obwohl ausführlicher) verwendet werden kann, um das gewünschte Verhalten für Edge-Fälle an den Endbenutzer zu delegieren - was manchmal den Aufruf von erforderlich macht
cmp(x,0)
.Ich weiß nicht, warum es nicht eingebaut ist, aber ich habe einige Gedanken.
Am wichtigsten
copysign
ist, eine Obermenge vonsign
! Das Aufrufencopysign
mit x = 1 entspricht einersign
Funktion. Sie können es also einfach verwendencopysign
und vergessen .Wenn Sie es satt haben, zwei ganze Argumente zu übergeben, können Sie dies auf
sign
diese Weise implementieren , und es ist weiterhin mit den von anderen erwähnten IEEE-Inhalten kompatibel:Zweitens, normalerweise, wenn Sie das Zeichen von etwas wollen, multiplizieren Sie es einfach mit einem anderen Wert. Und natürlich ist das im Grunde was
copysign
macht natürlich.Also statt:
Sie können einfach tun:
Und ja, ich bin überrascht, dass Sie Python seit 7 Jahren verwenden und denken,
cmp
dass es so einfach entfernt und ersetzt werden kannsign
! Haben Sie noch nie eine Klasse mit einer__cmp__
Methode implementiert ? Hast du noch nie angerufen?cmp
eine benutzerdefinierte Komparatorfunktion und angegeben?Zusammenfassend wollte ich auch eine
sign
Funktion, abercopysign
mit dem ersten Argument 1 wird es gut funktionieren. Ich bin nicht der Meinung, dasssign
dies nützlicher wäre alscopysign
, da ich gezeigt habe, dass es sich lediglich um eine Teilmenge derselben Funktionalität handelt.quelle
[int(copysign(1, zero)) for zero in (0, 0.0, -0.0)]
gibt gibt[1, 1, -1]
. Das sollte[0, 0, 0]
laut en.wikipedia.org/wiki/Sign_functioncopysign(a,b)
gibt a mit dem Vorzeichen von b zurück - b ist die variierende Eingabe, a ist der Wert, auf den mit dem Vorzeichen von b normalisiert werden soll. In diesem Fall zeigt der Kommentator, dass das Copysign (1, x) als Ersatz für das Zeichen (x) fehlschlägt, da es 1 für x = 0 zurückgibt, während das Zeichen (0) 0cmp()
führt zu den gewünschten Ergebnissen, wahrscheinlich für fast jeden Fall, den jemand interessieren würde:[cmp(zero, 0) for zero in (0, 0.0, -0.0, -4, 5)]
==>[0, 0, 0, -1, 1]
.s = sign(a) b = b * s
ist nicht gleichbedeutend mitb = copysign(b, a)
! Das Vorzeichen von b wird nicht berücksichtigt. ZB wenna=b=-1
der erste Code 1 zurückgibt, während der zweite -1 zurückgibt"Copysign" ist in IEEE 754 definiert und Teil der C99-Spezifikation. Deshalb ist es in Python. Die Funktion kann nicht vollständig durch abs (x) * -Zeichen (y) implementiert werden, da sie mit NaN-Werten umgehen soll.
Das macht copysign () zu einer nützlicheren Funktion als sign ().
Was bestimmte Gründe angeht, warum das IEEE-Signbit (x) in Standard-Python nicht verfügbar ist, weiß ich nicht. Ich kann Annahmen treffen, aber es wäre eine Vermutung.
Das Mathematikmodul selbst verwendet Copysign (1, x), um zu überprüfen, ob x negativ oder nicht negativ ist. In den meisten Fällen handelt es sich um mathematische Funktionen, die nützlicher erscheinen als ein Vorzeichen (x), das 1, 0 oder -1 zurückgibt, da ein Fall weniger zu berücksichtigen ist. Das Folgende stammt beispielsweise aus Pythons Mathematikmodul:
Dort können Sie deutlich sehen, dass copysign () eine effektivere Funktion ist als eine dreiwertige sign () -Funktion.
Sie schrieben:
Das heißt, Sie wissen nicht, dass cmp () nicht nur für Zahlen verwendet wird. cmp ("This", "That") kann nicht mit einer sign () - Funktion implementiert werden.
Bearbeiten, um meine zusätzlichen Antworten an anderer Stelle zusammenzustellen :
Sie begründen Ihre Rechtfertigung damit, wie oft abs () und sign () zusammen gesehen werden. Da die C-Standardbibliothek keinerlei 'sign (x)' - Funktion enthält, weiß ich nicht, wie Sie Ihre Ansichten begründen. Es gibt eine abs (int) und fabs (double) und fabsf (float) und fabsl (long), aber keine Erwähnung des Zeichens. Es gibt "copysign ()" und "signbit ()", diese gelten jedoch nur für IEEE 754-Nummern.
Was würde bei komplexen Zahlen das Zeichen (-3 + 4j) in Python zurückgeben, sollte es implementiert werden? abs (-3 + 4j) gibt 5,0 zurück. Dies ist ein klares Beispiel dafür, wie abs () an Stellen verwendet werden kann, an denen sign () keinen Sinn ergibt.
Angenommen, Zeichen (x) wurden Python als Ergänzung zu abs (x) hinzugefügt. Wenn 'x' eine Instanz einer benutzerdefinierten Klasse ist, die die Methode __abs __ (self) implementiert, ruft abs (x) x .__ abs __ () auf. Um korrekt zu arbeiten und abs (x) auf die gleiche Weise zu behandeln, muss Python einen Vorzeichen (x) -Slot erhalten.
Dies ist für eine relativ unnötige Funktion übermäßig. Außerdem, warum sollte das Zeichen (x) existieren und das nichtnegative (x) und das nichtpositive (x) nicht existieren? Mein Ausschnitt aus der Implementierung des Python-Mathematikmoduls zeigt, wie Copybit (x, y) verwendet werden kann, um nonnegative () zu implementieren, was ein einfaches Zeichen (x) nicht kann.
Python sollte eine bessere Unterstützung für die mathematische Funktion IEEE 754 / C99 bieten. Das würde eine Signbit (x) -Funktion hinzufügen, die im Fall von Floats tun würde, was Sie wollen. Es würde nicht für ganze Zahlen oder komplexe Zahlen funktionieren, geschweige denn für Zeichenfolgen, und es würde nicht den Namen haben, den Sie suchen.
Sie fragen "warum" und die Antwort lautet "Zeichen (x) ist nicht nützlich". Sie behaupten, dass es nützlich ist. Ihre Kommentare zeigen jedoch, dass Sie nicht genug wissen, um diese Behauptung aufstellen zu können, was bedeutet, dass Sie überzeugende Beweise für ihre Notwendigkeit vorlegen müssten. Zu sagen, dass NumPy es implementiert, ist nicht überzeugend genug. Sie müssten Fälle zeigen, wie vorhandener Code mit einer Zeichenfunktion verbessert wird.
Und das außerhalb des Bereichs von StackOverflow. Nehmen Sie es stattdessen zu einer der Python-Listen.
quelle
cmp()
nochsign()
:-)Ein weiterer Liner für Zeichen ()
Wenn Sie möchten, dass 0 für x = 0 zurückgegeben wird:
quelle
cmp(x, 0)
äquivalentsign
undlambda x: cmp(x, 0)
lesbarer ist als das, was Sie vorschlagen.-1 if x < 0 else 1
?sign = lambda x: -1 if x < 0 else 1
ist 15% schneller . Gleiches gilt fürsign = lambda x: x and (-1 if x < 0 else 1)
.Da
cmp
wurde entfernt , können Sie die gleiche Funktionalität mit erhaltenEs funktioniert für
float
,int
und sogarFraction
. Im Falle vonfloat
, beachten Siesign(float("nan"))
Null.Python erfordert nicht, dass Vergleiche einen Booleschen Wert zurückgeben. Das Erzwingen der Vergleiche mit bool () schützt daher vor zulässigen, aber ungewöhnlichen Implementierungen:
quelle
Nur korrekte Antwort gemäß Wikipedia-Definition
Die Definition auf Wikipedia lautet:
Daher,
Was in jeder Hinsicht vereinfacht werden kann, um:
Diese Funktionsdefinition wird schnell ausgeführt und liefert garantiert korrekte Ergebnisse für 0, 0,0, -0,0, -4 und 5 (siehe Kommentare zu anderen falschen Antworten).
Beachten Sie, dass Null (0) weder positiv noch negativ ist .
quelle
numpy hat eine Vorzeichenfunktion und bietet Ihnen auch einen Bonus für andere Funktionen. So:
Achten Sie nur darauf, dass das Ergebnis numpy.float64 ist:
Für Dinge wie json ist dies wichtig, da json nicht weiß, wie numpy.float64-Typen serialisiert werden. In diesem Fall könnten Sie Folgendes tun:
einen regelmäßigen Schwimmer zu bekommen.
quelle
Versuchen Sie dies auszuführen, wobei x eine beliebige Zahl ist
Der Zwang zu bool () behandelt die Möglichkeit, dass der Vergleichsoperator keinen Booleschen Wert zurückgibt.
quelle
Ja, eine korrekte
sign()
Funktion sollte zumindest im Mathematikmodul vorhanden sein - da es sich um eine Zahl handelt. Weil man es häufig für mathematisch orientierten Code benötigt.Ist
math.copysign()
aber auch unabhängig nützlich.cmp()
undobj.__cmp__()
... haben in der Regel unabhängig eine hohe Bedeutung. Nicht nur für mathematisch orientierten Code. Betrachten Sie das Vergleichen / Sortieren von Tupeln, Datumsobjekten, ...Die Entwicklerargumente unter http://bugs.python.org/issue1640 bezüglich des Auslassens von
math.sign()
sind seltsam, weil:-NaN
sign(nan) == nan
ohne Sorge (wieexp(nan)
)sign(-0.0) == sign(0.0) == 0
ohne Sorgesign(-inf) == -1
ohne Sorge- wie es in numpy ist
quelle
Gibt in Python 2
cmp()
eine Ganzzahl zurück: Es ist nicht erforderlich, dass das Ergebnis -1, 0 oder 1 ist, dahersign(x)
ist es nicht dasselbe wiecmp(x,0)
.In Python 3 wurde
cmp()
zugunsten eines reichhaltigen Vergleichs entfernt. Fürcmp()
Python 3 schlägt dies vor :Dies ist in Ordnung für cmp (), kann jedoch nicht für sign () verwendet werden, da die Vergleichsoperatoren keine Booleschen Werte zurückgeben müssen .
Um mit dieser Möglichkeit umzugehen, müssen die Vergleichsergebnisse zu Booleschen Werten gezwungen werden:
Dies funktioniert für alle,
type
die vollständig geordnet sind (einschließlich spezieller Werte wieNaN
oder Unendlichkeiten).quelle
Sie brauchen keine, Sie können nur verwenden:
quelle
x / abs(x)
etwas länger dauert, als nur zu verkettenif/else
, um zu überprüfen, auf welcher Seite von 0 sich die Variable befindet, oder ob Sie schleimig und dennoch zufriedenstellend sind,return (x > 0) - (x < 0)
umbool
Werte zu subtrahieren und einenint
True
undFalse
wie1
und0
Sie können absolut dies tun und entweder bekommen1
,0
oder-1
.def sign(x): return (x > 0) - (x < 0)
wird kein zurückgebenbool
, es wird ein zurückgebenint
- wenn Sie bestehen, erhalten0
Sie0
zurückDas tut es einfach nicht.
Der beste Weg, dies zu beheben, ist:
quelle
Der Grund, warum "Zeichen" nicht enthalten ist, ist, dass es nicht mehr einfach und praktisch wäre, mit Python zu arbeiten, wenn wir jeden nützlichen Einzeiler in die Liste der integrierten Funktionen aufnehmen würden. Wenn Sie diese Funktion so oft verwenden, warum nehmen Sie sie dann nicht selbst heraus? Es ist nicht so, als wäre es aus der Ferne schwierig oder sogar langweilig, dies zu tun.
quelle
abs()
es auch weggelassen würde.sign()
undabs()
werden oft zusammen verwendet,sign()
ist die nützlichste der beiden (IMO), und keine ist aus der Ferne schwer oder mühsam zu implementieren (obwohl sie fehleranfällig ist, sehen Sie, wie diese Antwort falsch ist: stackoverflow.com/questions/1986152/… )sign()
selbst selten nützlich ist. Meistens verwenden Sie unterschiedliche Codepfade, je nachdem, ob eine Variable positiv oder negativ ist. In diesem Fall ist es besser lesbar, die Bedingung explizit zu schreiben.