(Es ist kein übersetzter Artikel) Nein.
Vielleicht ist es gut, nicht wahr? Es macht es sehr einfach, mit dem Zustand eines Wertes und dem Zustand ohne Wert umzugehen. Es ist der Höhepunkt der von Lirin geschaffenen Kultur.
Also dachte ich, ich könnte etwas Ähnliches mit Python machen und implementierte es.
Der Hauptteil ist [hier] aufgeführt (https://gist.github.com/BlueRayi/fb999947e8f2a8037e7eea7ff9320f90). Ich denke, du solltest auf jeden Fall Masakari spielen und werfen.
Einige von ihnen sind sich ausdrücklich bewusst, dass "null unsichere Sprachen keine Legacy-Sprachen mehr sind". Lesen Sie sie daher bitte zusammen. Ich denke es ist gut.
Dieses Vielleicht wird als konkrete Klassen "Etwas" und "Nichts" implementiert, die von der abstrakten Klasse "Vielleicht" erben. "Etwas" zeigt an, dass ein Wert vorhanden ist, und "Nichts" zeigt an, dass der Wert fehlt.
Die Funktion "nur" erstellt eine Instanz von "etwas". "nichts" ist die (einzige) Instanz von "nichts".
from maybe import just, nothing
a = just(42)
b = nothing
print(a)
print(b)
Just 42
Nothing
Vielleicht hat die Eigenschaft "has_value", "Something" gibt "True" zurück und "Nothing" gibt "False" zurück. Auch "Etwas" ist selbst Wahrheit und "Nichts" ist selbst Falsey.
print(a.has_value)
print(b.has_value)
print('-----')
if a:
print('a is Truthy')
else:
print('a is Falsy')
if b:
print('b is Truthy')
else:
print('b is Falsy')
True
False
-----
a is Truthy
b is Falsy
Vielleicht kann man sich eine Box vorstellen, in die man Werte einfügen kann. Vielleicht kann selbst ein Wert sein, also kann vielleicht verschachtelt werden. Vielleicht hat das Konzept der "Tiefe". Die Tiefe des bloßen Werts beträgt 0. Die Tiefe von "Nichts" ist 1. Die Tiefe von "Etwas" ist "Inhaltstiefe + 1". Die Tiefe kann erhalten werden, indem sie an die Funktion "dep" übergeben wird.
from maybe import dep
a2 = just(a)
b2 = just(b)
print(a2)
print(b2)
print('-----')
print(dep(42))
print(dep(a))
print(dep(b))
print(dep(a2))
print(dep(b2))
Just Just 42
Just Nothing
-----
0
1
1
2
2
Vielleicht können gleiche Werte verglichen werden. "Etwas" wird als gleich angenommen, wenn sie "Etwas" sind und ihr Inhalt gleich ist. Wenn es sich um eine verschachtelte Struktur handelt, wird sie während der Rekursion ausgegraben. "Nichts" wird als gleich angenommen, wenn sie "Nichts" sind.
print(a == 42)
print(a == just(42))
print(a == a2)
print(a == b)
print(b == nothing)
print(b == b2)
print(b2 == just(nothing))
False
True
False
False
True
False
True
Um "Vielleicht [T]" als "T" zu verwenden,
Es ist möglich, es wie folgt zu verwenden, indem die if-Anweisung und der später beschriebene erzwungene Entpackungsoperator verwendet werden.
m = just(913)
if m.has_value:
print(m.i + 555)
1488
Wenn diese beiden Prozesse jedoch getrennt werden, können die folgenden unerwarteten Ereignisse auftreten.
m = just(913)
if m.has_value:
print(m + 555) #Vergessen Sie vielleicht das Auspacken[int]Und int kann nicht hinzugefügt werden
TypeError: unsupported operand type(s) for +: 'Something' and 'int'
m = nothing
print(m.i + 555) #Vergiss die Nullprüfung, wenn m Nichts ist, die schleimige Fliege
maybe.NullpoError: it GOT no value.
Vielleicht kann Vielleicht iteriert werden, "Etwas" generiert den Wert des Inhalts nur einmal, und "Nichts" generiert nichts und löst eine "StopIteration ()" - Ausnahme aus. Auf diese Weise können Sie die for-Anweisung verwenden, um eine Nullprüfung durchzuführen und gleichzeitig wie unten gezeigt umzuwandeln.
m = just(913)
for v in m:
print(v + 555) #Dies wird nur ausgeführt, wenn m etwas ist
1468
Ich nenne dies die "Vielleicht-Bindung", weil es sich genauso anfühlt wie die Swift Optional-Bindung. Der Unterschied zur optionalen Bindung besteht darin, dass keine Abschattung (unter Verwendung des gleichen Variablennamens im Block) möglich ist und die Verzweigung zwischen fehlenden Werten etwas kompliziert ist.
Schauen wir sie uns der Reihe nach an. Wenn Sie aufgrund des variablen Bereichs von Python so etwas wie Shadowing ausführen, ändert sich "m" in der Kommentarzeile von "Vielleicht [int]" zu "int".
m = just(913)
print(m) #Hier vielleicht[int]
for m in m:
print(m + 555)
print(m) #Hier int
Just 913
1468
913
Denken Sie, dass dies bequemer ist, weil Sie bereits Null aktiviert haben? Aber es ist eine Falle. Wenn der Wert von "m" fehlt, bleibt er "Vielleicht [int]". Sie dürfen sich von nun an nicht mehr mit "m" im selben Kontext wie "Vielleicht" befassen. Sie müssen Ihre Zeit damit verbringen, Angst vor der Möglichkeit zu haben, dass "m", das wie "int" aussieht, "nichts" ist. Ich weiß nicht, wofür Vielleicht ist. Ist es nicht viel anders als nur "Keine" zu verwenden (in der Tat ist es problematischer)?
Der nächste Unterschied. Möglicherweise möchten Sie den Prozess mit und ohne Wert verzweigen, anstatt ihn nur dann auszuführen, wenn ein Wert vorhanden ist. In Swift Optional können Sie wie folgt schreiben.
let m: Int? = nil
if let v = m {
print(v + 555)
} else {
print("Vielleicht hasst du mich?")
}
Die Entsprechung zwischen "wenn" und "sonst" ist schön und konkurrenzlos. Und diese beiden Blöcke sind grammatikalisch gepaart.
In Vielleicht müssen wir jedoch so schreiben.
m = nothing
for v in m:
print(v + 555)
if not m.has_value:
print("Vielleicht hasst du mich?")
Die Korrespondenz zwischen "für" und "wenn" wurde wahrscheinlich geboren und niemand hat sie jemals gesehen. Außerdem sind diese beiden Blöcke nebeneinander geschrieben und kein grammatikalisches Paar. Außerdem ist "wenn nicht m.has_value" ziemlich lang. In Bezug darauf ist "Nichts" ursprünglich Falsey, also "wenn nicht" ist in Ordnung, aber es gibt einen Nachteil, dass die Bedeutung des Textes etwas schwer zu lesen ist.
Das heißt, es ist viel sicherer und einfacher zu schreiben, als wenn der Null-Check und die Besetzung getrennt sind. Grundsätzlich ist es besser, die Verwendung von ".i" zu verbieten und die Vielleicht-Bindung zu verwenden.
!
, !!
)Stellen Sie sich eine Funktion safe_int
vor, die versucht, von str
nach int
zu konvertieren, und bei einem Fehlschlag nothing
zurückgibt.
def safe_int(s):
try:
return just(int(s))
except ValueError:
return nothing
Angenommen, diese Funktion enthält eine Zeichenfolge, die aus dem Textfeld "Alter" springt, das auf einer bestimmten Site verwendet wird. Normalerweise dürfen Sie nur Zahlen auf der HTML-Seite eingeben, und die Vorverarbeitung erfolgt in der vorherigen Phase mit JavaScript.
In solchen Fällen ist es für diese Funktion praktisch unmöglich, "nichts" zurückzugeben. Trotzdem kann "Vielleicht [int]" nicht als "int" verwendet werden. Muss ich also lange Zeit eine Vielleicht-Bindung schreiben? Dann ist es besser, "Keine" zu verwenden.
Dann sollten Sie den erzwungenen Entpackungsoperator ".i" verwenden. Übrigens, obwohl es als Operator bezeichnet wird, ist es tatsächlich eine Eigenschaft.
s = get_textbox('Alter')
age = safe_int(s).i # .Ich weise dem Alter eine ganze Zahl zu
if age >= 20:
...
Es scheint bequem und problemlos zu sein, aber wenn Sie ".i" für "nichts" nennen, wird der gute alte den ursprünglichen "NullpoError" fliegen. Auch hier wird der erzwungene Entpackungsoperator als "unsichere" Operation betrachtet und sollte nur verwendet werden, wenn er in der Logik niemals "nichts" sein kann.
? .
,? ->
)Angenommen, Sie haben hier eine "Vielleicht [Liste]". Sie wollten herausfinden, wie viele Nullen darin enthalten sind. Ich denke, vielleicht könnte "nichts" sein, aber die meiste Zeit, wenn die Liste selbst nicht existiert, würde man "nichts" erwarten (nein, einige Leute wollen "0"). Siehe auch den folgenden „Null-Heilungsoperator“.
Um ehrlich zu sein, sieht es so aus:
l = get_foobar_list('hogehoge')
for l0 in l:
num_0 = just(l0.count(0))
if not l:
num_0 = nothing
Ich kann es sicher schreiben, aber um klar zu sein, es ist kompliziert. Wenn l`` list
ist, möchten Sie den Prozess, dernum_0 = l.count (0)
erfordert, nicht über 4 Zeilen schreiben.
Sie können es mit dem Null-Bedingungsoperator .q.
präzise schreiben (wie üblich ist es wirklich eine Eigenschaft).
l = get_foobar_list('hogehoge')
num_0 = l.q.count(0)
Sie können .q []
auch für Indizes verwenden.
l = get_foobar_list('hogehoge')
print(l.q[3])
#Kann anstelle von verwendet werden
# for l0 in l:
# print(just(l0[3]))
# if not l:
# print(nothing)
Warum können wir das tun? .Q
gibt ein Objekt zurück, das von der abstrakten Klasse SafeNavigationOperator
erbt. SafeNavigationOperator
überschreibt __getattr__
und __getitem__
. Wenn es einen Wert hat, wird "Something SNO" zurückgegeben. Dies enthält die Wertinformationen und __getattr__
und __getitem__
wickeln sie in just
ein und geben sie zurück. Wenn der Wert fehlt, wird "NothingSNO" zurückgegeben, und "getattr" und "getitem" geben einfach "nichts" zurück.
Sie fragen sich vielleicht, ob Sie hier eine gute Idee haben. some_list.count
ist eine Methode und ein aufrufbares Objekt. Maybe_list.q.count
wird zurückgegeben, indem die Funktion in Vielleicht weiter eingeschlossen wird. Ist es ein aufrufbares Objekt von Vielleicht selbst, dass es wie "l.q.count (0)" behandelt werden kann?
In der Tat ist das richtig. Wenn Sie "Something" aufrufen, wird der Inhalt aufgerufen und das Ergebnis in "just" eingeschlossen und zurückgegeben. Das Aufrufen von "Nichts" gibt einfach "Nichts" zurück. Diese Spezifikation ermöglicht es, die oben genannten Dinge zu tun. Diese Spezifikation ist gleichzeitig mit ".q." zu verwenden. Ich persönlich halte es für magisch, es auf andere Weise zu verwenden, daher halte ich es für besser, es nicht zu verwenden (dies führt zu dem Grund, warum die vier Regeln von Vielleicht, die später beschrieben werden, nicht implementiert werden).
Übrigens, selbst unter den Sprachen, die "?" Implementieren, endet die sogenannte "optionale Kette", wenn Null gefunden wird (sozusagen Kurzschlussauswertung), aber ".q." Im Fall von wird der Prozess mit "nichts" fortgesetzt. Selbst wenn Sie ".q." für "nichts" tun, erhalten Sie nur "nichts", und das Ergebnis der Weitergabe entspricht immer noch Null, aber Sie sollten sich dieses Unterschieds bewusst sein. Möglicherweise müssen Sie es behalten.
Übrigens können Sie so etwas wie foo.q.bar = baz
nicht machen, weil Sie __setattr__
nicht überschrieben haben. Dies ist meine technische Einschränkung und ich konnte die Endlosschleife, die beim Überschreiben von __setattr__
auftritt, einfach nicht lösen. Bitte hilf mir ... Ich denke, dass foo.q [bar] = baz
gemacht werden kann, aber es ist bisher nicht implementiert, weil die Symmetrie gebrochen ist.
?:
, ??
)Im Fall von Null ist das Ausfüllen mit dem Standardwert wahrscheinlich die häufigste Anforderung beim Umgang mit Null.
Natürlich kann man auch mit Vielleicht verbindlich schreiben, aber ...
l = get_foobar_list('hogehoge')
num_0 = l.q.count(0) #Übrigens, hier ist num_0 ist vielleicht[int]damit……
for v in num_0:
num_0 = v
if not num_0:
num_0 = 0
#Wenn Sie hier rauskommen, num_0 wird int.
Der Null-Fusionsoperator [^ coalesce] >>
ist ordnungsgemäß vorbereitet.
l = get_foobar_list('hogehoge')
num_0 = l.q.count(0) >> 0 # num_0 ist int
Das Verhalten des Null-Fusionsoperators sieht auf den ersten Blick einfach aus (und ist eigentlich einfach), erfordert jedoch ein wenig Aufmerksamkeit.
Wenn der Wert auf der linken Seite fehlt, ist die Geschichte einfach und die rechte Seite wird so zurückgegeben, wie sie ist.
Wenn andererseits die linke Seite einen Wert hat, verhält sie sich interessant (im translatorischen Sinne von Interessant). Wenn die linke Seite tiefer als die rechte Seite ist, werden der Inhalt der linken und der rechten Seite wieder vereint. Wenn die rechte Seite tiefer als die linke Seite ist, wickeln Sie die linke Seite mit "nur" ein und heilen Sie dann erneut. Wenn sie gleich sind, wird die linke Seite zurückgegeben. Wenn die rechte Seite jedoch ein bloßer Wert ist (Tiefe 0), wickeln Sie die rechte Seite in "just" ein und vereinheitlichen Sie den Inhalt erneut und geben Sie ihn zurück.
Der Operator "oder", der sich von außen ähnlich verhält, ist viel komplizierter als die Rückgabe, wenn die linke Seite "Wahrheit" ist. Der Grund dafür ist, dass aufgrund eines rekursiven Aufrufs immer ein Wert mit der gleichen Tiefe wie auf der rechten Seite zurückgegeben wird.
Im Zusammenhang mit dem Festlegen eines Standardwerts würden Sie erwarten, dass dieser mit oder ohne Wert gleich behandelt wird. Möglicherweise kann verschachtelt werden, so dass einige umständliche Operationen erforderlich sind. Dies ist jedoch eine interne Geschichte, und der Benutzer kann sie einfach als „immer einen Wert mit derselben Struktur zurückgeben“ behandeln.
Wenn es beispielsweise mehrere Vielleicht gibt, können Sie unabhängig von ihrer Struktur wie folgt "Vielleicht mit derselben Struktur wie die Seite ganz rechts (in diesem Fall bloßer Wert), wo der Wert am frühesten erscheint" erhalten. Ich werde.
x = foo >> bar >> baz >> qux >> 999
Beachten Sie jedoch, dass die rechte Seite ausgewertet wird, da es sich nicht um eine Kurzschlussbewertung handelt.
Dieser Operator wird übrigens durch Überladen des richtigen Bitverschiebungsoperators implementiert. Daher ist auch die Berechnungspriorität gleich. Das heißt, es ist niedriger als der Additionsoperator und höher als der Vergleichsoperator [^ Operator-Priorität]. Dies liegt nahe an der Priorität des Null-Fusionsoperators von C # [^ c-scharf], Swift [^ swift], Kotlin [^ kotlin], aber andererseits des in PEP 505 vorgeschlagenen "nicht-bewussten Operators". Dies unterscheidet sich sehr von [^ pep-505], wo ?? eine höhere Priorität hat als die meisten binären Operatoren. Bitte seien Sie vorsichtig, wenn der Tag, an dem PEP 505 offiziell verabschiedet wird (ich glaube nicht, dass es kommen wird). Außerdem wird
>> =` automatisch definiert.
a = just(42)
b = nothing
print(a >> 0 + 12) # 42 ?? 0 +12 wäre 54(Haz)
print('-----')
a >>= 999
b >>= 999
print(a)
print(b)
42
-----
42
999
Nebenbei habe ich ">>" als Überlastungsziel gewählt.
Und so weiter. ~~ Es scheint, dass je niedriger Sie gehen, desto rationaler der Grund, aber das Beängstigende ist, dass je niedriger Sie gehen, desto mehr der Grund für die Nachrüstung ist und Sie sehen können, dass der Autor Vielleicht angemessen gemacht hat. ~~
[^ Koaleszenz]: Im Allgemeinen lautet die Standardübersetzung des Null-Koaleszenz-Operators "Null-Koaleszenz-Operator", aber "Koaleszenz" fehlt die Nuance "Ausfüllen des fehlenden Teils", was "Wunde schließen" bedeutet. "Heilung" wird verwendet.
map
Methode (von map
)Der Null-Bedingungsoperator hat tatsächlich seine Schwächen. Es kann nur mit Vielleicht-Objekten verwendet werden. Sie können "SafeNavigationOperator" auch nicht als Argument angeben.
Das bedeutet, dass Sie dies nicht tun können.
l = just([1, 2, 3, ])
s = .q.sum(l) #Syntax-Fehler
s = sum(l.q) #Ausnahme zum Pop
#Warum machst du das nicht?
#Oah, oh, oh, oh, oh, ♥
Sie können mit Vielleicht Bindung schreiben, aber es ist immer noch kompliziert.
l = just([1, 2, 3, ])
for l0 in l:
s = just(sum(l0))
if not l:
s = nothing
Es gibt eine "Map" -Methode, um dies von der Objektseite "Vielleicht" aus zu tun. Mit der map
Methode können Sie schreiben:
l = just([1, 2, 3, ])
s = l.map(sum)
Die an die map
-Methode übergebene Funktion gibt das in just
eingeschlossene Ergebnis zurück. Wenn der Wert fehlt, wird natürlich "nichts" zurückgegeben. Sie können auch Lambda-Ausdrücke für Funktionen verwenden, um Folgendes zu tun:
a = just(42)
print(a.map(lambda x: x / 2))
Just 21.0
Über die "Map" -Methode gibt es nicht viel zu sagen (besonders wenn Sie Monad kennen).
bind
Methode (von flatMap
)Erinnern Sie sich an die zuvor erstellte Funktion "safe_int". Es nimmt "str" als Argument und gibt "Vielleicht [int]" zurück. Wenden wir dies mit map
aufVielleicht [str]
an.
s1 = just('12')
s2 = just('hogehoge')
s3 = nothing
print(s1.map(safe_int))
print(s2.map(safe_int))
print(s3.map(safe_int))
Just Just 12
Just Nothing
Nothing
safe_int
gibt Vielleicht zurück, und die map
-Methode umschließt es mit just
, sodass es verschachtelt ist. Vielleicht wollte die Person, die dieses Programm geschrieben hat, dieses Ende nicht (die Tatsache, dass "verschachtelt werden kann", macht es aussagekräftiger. Wenn das Ergebnis der JSON-Analyse beispielsweise "null" enthält, dann "nur" (nichts) , denn wenn der Schlüssel überhaupt nicht existiert hätte, könnte er als
nichts` ausgedrückt werden).
Bisher wurde es geheim gehalten, aber Sie können die Join-Funktion verwenden, um die Nester in einem Schritt zu zerstören. Es ist eine natürliche Umwandlung μ.
from maybe import join
print(join(s1.map(safe_int)))
print(join(s2.map(safe_int)))
print(join(s3.map(safe_int)))
Just 12
Nothing
Nothing
Und vor allem ist es wünschenswert, "map" und "join" zu kombinieren. Wenn Sie eine Bindemethode haben, können Sie diese verwenden.
print(s1.bind(safe_int))
print(s2.bind(safe_int))
print(s3.bind(safe_int))
Just 12
Nothing
Nothing
Für diejenigen, die die Haskell ~~ Transformation ~~ beherrschen, können Sie leicht verstehen, dass die map
Methode der <$>
Operator und die bind
Methode der >> =
Operator ist. Denken Sie daran, "map" für Funktionen, die nackte Werte zurückgeben, und "bind" für Funktionen, die "Maybe" zurückgeben.
do
Funktion (von do
Notation)Natürlich werden map
und bind
von einem Maybe-Objekt aufgerufen, daher ist es etwas schwierig, sie für Funktionen zu verwenden, die zwei oder mehr Argumente annehmen.
lhs = just(6)
rhs = just(9)
ans = lhs.bind(lambda x: rhs.map(lambda y: x * y))
print(ans)
Just 54
Das Innere ist übrigens "map", weil es eine Funktion ist, die einen bloßen Wert mit "x * y" zurückgibt, und das Äußere ist "bind", weil der Rückgabewert der "map" -Methode "Maybe" ist. Erinnerst du dich?
Sie können dies einfach mit der Funktion "do" schreiben.
from maybe import just, nothing, do
lhs = just(6)
rhs = just(9)
ans = do(lhs, rhs)(lambda x, y: x * y)
print(ans)
Just 54
Die Funktion "do" extrahiert den Inhalt und führt die Funktion nur aus, wenn alle Argumente Werte haben. Gibt "nichts" zurück, wenn ein Wert fehlt. Der Name "do" stammt von Haskell, aber der Algorithmus ist extrem anti-monadisch. Vergib mir.
Das Argument der Funktion "do" kann übrigens nur von Maybe übernommen werden. Wenn Sie bloße Werte als Argumente verwenden möchten, schließen Sie sie in "nur" ein.
Vielleicht ist auch ein Container, und Sie können die Operatoren "len" und "in" verwenden.
Die len
Funktion gibt immer 1
für Something
und 0
für Nothing
zurück.
a = just(42)
b = nothing
a2 = just(a)
b2 = just(b)
print(len(a))
print(len(b))
print(len(a2))
print(len(b2))
1
0
1
1
Der Operator "in" gibt "True" zurück, wenn der Inhalt der rechten Seite gleich der linken Seite ist. Andernfalls wird "False" zurückgegeben. Nothing
gibt immer False
zurück.
print(42 in a)
print(42 in b)
print(42 in a2)
print(42 in b2)
True
False
False
False
Wie bereits erwähnt, kann Vielleicht iterativ sein. So können Sie es beispielsweise in eine Liste konvertieren. @koher sagte: Genau das ist das Ergebnis.
Optional
war eine Box, die möglicherweise leer ist. Unter einem anderen Gesichtspunkt können Sie sich "Optional" als "Array" vorstellen, das höchstens ein Element enthalten kann.
al = list(a)
bl = list(b)
print(al)
print(bl)
[42]
[]
Es ist ein Rätsel, ob es hier die Möglichkeit gibt, die Spezifikationen zu verwenden.
Vielleicht hat ein Paar Funktionen und Methoden, vielleicht_von
und to_native
. Es ist ein Paar von Funktionen und Methoden. Diese arbeiten, um die nativen Python-Typen mit Maybe zu verbinden.
Maybe_from
nimmt einen nativen Wert und gibt Vielleicht zurück. Der Unterschied zu "nur" besteht darin, dass bei "Keine" "nichts" anstelle von "nur (keine)" zurückgegeben wird und wenn "Vielleicht" angegeben wird, es so zurückgegeben wird, wie es ist. Diese Funktion kann verwendet werden, um gemeinsam die Rückgabewerte vorhandener Funktionen und Methoden zu verwenden, die fehlende Rückgabewerte im allgemeinen Kontext von Vielleicht als "Keine" anzeigen.
#Bestehende Funktion, die None anstelle von price zurückgibt, wenn sie nicht im Wörterbuch enthalten ist
def get_price(d, name, num, tax_rate=0.1):
if name in d:
return -(-d[name] * num * (1 + tax_rate)) // 1
else:
return None
# ...
from maybe import maybe_from
p = get_price(unit_prices, 'apple', 5) #int kann kommen, niemand darf kommen
p = maybe_from(p) #p ist Einheit_zu Preisen'apple'Vielleicht mit oder ohne[int]
Die Methode "to_native" macht "Vielleicht" zu einem nativen Wert (obwohl es nur ein nativer Wert ist, wenn der Inhalt ein Objekt ist, das von einer Bibliothek bereitgestellt wird). Im Gegensatz zu ".i" gibt "nichts" "Keine" zurück (aber missbrauchen Sie es nicht als "sicheren" Unwrap-Operator), und selbst wenn es verschachtelt ist, gräbt es rekursiv und ist immer nackt. Gibt den Wert von zurück. map
betrachtet das Ganze als fehlend, wenn das Argument fehlt, aber dies kann als Argument für eine Funktion verwendet werden, die erwartet, dass None
keinen Wert bedeutet. Sie können es auch als JSON-Serialisierungsmethode angeben, indem Sie die Tatsache verwenden, dass es einen nativen Wert zurückgibt (obwohl es als nativ abgekürzt wird).
import json
from maybe import Maybe
def json_serial(obj):
if isinstance(obj, Maybe):
return obj.to_native()
raise TypeError ("Type {type(obj)} not serializable".format(type(obj)))
item = {
'a': just(42),
'b': nothing
}
jsonstr = json.dumps(item, default=json_serial)
print(jsonstr)
{"a": 42, "b": null}
Wenn Sie Vielleicht in Python sagen, gibt es eine vorhandene Bibliothek namens "PyMaybe". Es scheint ein berühmter Ort zu sein, der in PEP 505 erwähnt wird.
Das große Merkmal hier ist, dass Sie damit umgehen können, als ob es ein bloßer Wert wäre. Insbesondere der folgende Code in README.rst ist hilfreich. Stellen Sie sich hier "vielleicht" als "vielleicht_von" und hier "or_else" als ">>" Operator vor.
>>> maybe('VALUE').lower()
'value'
>>> maybe(None).invalid().method().or_else('unknwon')
'unknwon'
Wir rufen eine Methode für bloße Werte für Werte auf, die in Vielleicht eingeschlossen sind. Sie können auch sehen, dass der Methodenaufruf für Null ignoriert und Null weitergegeben wird. Sie müssen es nicht herausnehmen oder .q.
wie mein Vielleicht tun. Es scheint, dass auch Dunder-Methoden wie vier Regeln implementiert sind.
Warum ist das nicht bequemer? Ich denke, viele Leute denken, dass es keine zusätzlichen Fehler geben wird.
Es gibt jedoch einen Grund, warum ich Vielleicht mit einer solchen Spezifikation implementiert habe. Es geht nur darum, einen Fehler auszulösen.
Wenn Sie den Unterschied zwischen "Vielleicht [T]" und "T" nicht richtig erkennen, wird sofort eine Fehlermeldung angezeigt, die Ihnen hilft, den Unterschied zu erkennen. Wenn Sie es verwirren, erhalten Sie sofort eine Fehlermeldung. Wenn Sie es in einen String konvertieren, wird ihm ein zusätzliches "Just" vorangestellt. Es soll sichergestellt werden, dass "wenn Sie es nicht richtig schreiben, es nicht funktioniert". Wenn Sie einen Fehler machen, werden Sie ihn sofort bemerken (siehe: Wenn Sie es ernst meinen, haben Sie keine Angst vor dem optionalen Jahr (2018)). Dies ist auch der Grund, warum ich nicht möchte, dass Vielleicht direkt aufgerufen wird (weil es den Unterschied verbirgt, obwohl ich die Zeichenfolgenkonvertierung wirklich löschen möchte ...).
Es ist allgemein bekannt, dass die Nullsicherheit ein Mechanismus ist, der nicht schleimig ist, und es besteht kein Zweifel daran, dass der endgültige Zweck darin besteht (und plötzlich begann ich über die Nullsicherheit zu sprechen, aber meine Vielleicht sind die Typhinweise nutzlos, daher ist es praktisch unmöglich, sie für die Null-Sicherheit zu verwenden. Was jedoch für die Nullsicherheit wirklich notwendig ist, ist „eine Unterscheidung zwischen Nullable und Non-Null“. Warum ist Java nicht fehlgeschlagen? Sie konnten jedem Referenztyp "null" zuweisen, und umgekehrt konnte der Wert jedes Referenztyps "null" sein. Die Tatsache, dass "T" Null sein kann, bedeutet, dass Sie es nicht als "T" verwenden können, obwohl Sie "T" geschrieben haben. Sollte sein. Es ist ziemlich gefährlich, dorthin zu gelangen und die Barriere zwischen Nullable und Non-Null weiter zu durchbrechen - Dinge, die nicht "T" sind, wie "T" behandeln zu lassen - ist ziemlich gefährlich.
Objective-C hat eine schlechte Angabe, dass Methodenaufrufe an
nil
ohne Fehler ignoriert werden.(Weggelassen)
Als Gegenleistung für diese Bequemlichkeit birgt Objective-C jedoch auch ein schreckliches Risiko. Ich habe vergessen, das "Null" zu überprüfen, wo ich das "Null" hätte überprüfen sollen, aber manchmal funktioniert es einfach. Und eines Tages, wenn sich bestimmte Bedingungen überschneiden oder eine kleine Korrektur vorgenommen wird, wird der Fehler offensichtlich.
Der Umgang von Objective-C mit Nullen scheint auf den ersten Blick sicher zu sein, verzögert nur die Entdeckung von Problemen und erschwert deren Lösung. Ich halte die Objective-C-Methode für die schlechteste, da sie für potenzielle Fehler anfällig ist. Es war einmal, als ich ein in Objective-C geschriebenes Programm nach Java portierte, erst als in Java eine NullPointerException auftrat, wurde mir klar, dass die Nullbehandlung auf der Objective-C-Seite unangemessen war. war.
Das bedeutet natürlich nicht, dass Sie für die Null-Sicherheit weniger produktiv sein müssen. Eine Nullprüfung für nullfähige Variablen war „auch in der alten Sprache“ erforderlich [^ null-check], und dies implementierte möglicherweise eher verschiedene Möglichkeiten, um dies zu vereinfachen. Wenn Sie es treffen möchten, ohne Null zu aktivieren, gibt es dafür sogar eine unsichere Operation. Dieser Bereich ist [eine Geschichte, die vor einigen Jahren erzählt wurde](https://qiita.com/koher/items/e4835bd429b88809ab33#null-%E5%AE%89%E5%85%A8%E3%81%AF%E7 % 94% 9F% E7% 94% A3% E6% 80% A7% E3% 82% 82% E9% AB% 98% E3% 82% 81% E3% 82% 8B).
Ich denke jedoch, dass diejenigen, die Python verwenden möchten, sich dieser Robustheit und des Wertes bewusst sind, "schreibe, was du ehrlich schreiben willst". Ich kann also nicht sagen, dass PyMaybes Idee falsch ist ~~ Ich kann sagen, dass ich der "Vielleicht [T] -Fehler" bin, der sich gegen die Welt auflehnt ~~. Bitte zögern Sie jedoch nicht zu sagen, dass Sie halb spielen oder dass Sie geschrieben haben, was Sie schreiben möchten.
[^ null-check]: Dies ist eine unrealistische Geschichte für ein personalisiertes Vielleicht, aber wenn [nur "nichts" und nicht das eingebaute "Keine" verwenden](https://twitter.com/ kmizu / status / 782360813340286977) Wenn Sie können (wickeln Sie es in Maybe_from
ein, sobald es auftreten kann), müssen Sie keine Nullprüfung auf nackte Werte durchführen. Tatsächlich ist dies der größte Vorteil von Null-sicheren Sprachen, und Null-sichere Sprachen, deren Sprachspezifikationen einen solchen Mechanismus enthalten, müssen nur eine „notwendige Nullprüfung“ durchführen. Die allgemeine Auffassung, dass „Null-sichere Sprachen Nullprüfungen erzwingen“, ist richtig, aber das Gegenteil ist der Fall. Referenz: [Anti-Pattern] -Syndrom, das möglicherweise alle null (null) ist
Recommended Posts