Ich habe eine funktionale Sprache mit Python ausprobiert

Ich habe kürzlich Clojure aus irgendeinem Grund berührt.

Für diejenigen, die seit fast acht Jahren prozedurale Sprachen wie C und Python verwenden, gab es zunächst einige Verwirrung über "funktionale Sprachen", aber andererseits enthält Python viele der Vorteile funktionaler Sprachen. Ich habe es auch bemerkt.

Daher möchte ich anhand des Clojure-Beispiels ausprobieren, wie viel funktionale sprachähnliche Dinge mit Python erledigt werden können.

Dieses Mal veröffentlichte ayato-p Idioms von "Clojure's Japanese Guide". Lassen Sie uns den Inhalt von /clojure-beginner/idioms/index.html) in Python implementieren. Die vorliegende Version von Python ist 3.6.1.

Gruppieren Sie Elemente aus mehreren Sammlungen nach Index

[0 1 2 3 4]
[:a :b :c :d :e]

Da es in Python kein "Schlüsselwort" gibt, wird stattdessen eine Zeichenfolge verwendet. Mit Reißverschluss ist das ganz einfach.

a = [0, 1, 2, 3, 4]
b = [":a" ":b" ":c" ":d" ":e"]
zip(a, b)
# -> <zip at 0x111a14548>

Hoppla, Python 3 verwendet stark Iteratoren. Es wird nicht so ausgewertet, wie es ist. Wenn Sie also jedes Element sehen möchten, müssen Sie es in eine Liste aufnehmen.

list(zip(a, b))
# -> [(0, ':a'), (1, ':b'), (2, ':c'), (3, ':d'), (4, ':e')]

Konvertieren Sie die Karte in eine flache Sequenz

{:name    "ayato-p"
 :age     "24"
 :address "Japan"}

Verketten Sie (Schlüssel, Wert) Paare im Wörterbuch mithilfe der Kette im itertools-Modul. Das Sternchen "*" ist ein Operator zum Übergeben von Listenelementen als Funktionsargumente.

import itertools

d = {":name":    "ayato-p",
     ":age":     "24",
     ":address": "Japan"}

list(itertools.chain(*d.items()))
# -> [':name', 'ayato-p', ':age', '24', ':address', 'Japan']

Ich möchte Sequenzdaten an eine Funktion übergeben, die Argumente variabler Länge akzeptiert

(def v ["foo" "bar" "baz"])

(defn f [& args]
  (clojure.string/join ", " args))

Die Übergabe der Argumente ist die gleiche wie oben. Sie verwenden auch ein Sternchen, wenn Sie eine Funktion definieren, die Argumente variabler Länge akzeptiert.

v = ["foo", "bar", "baz"]

def f(*args):
    return ", ".join(args)

f(*v)
# -> 'foo, bar, baz'

Verwenden Sie beim Übergeben eines Wörterbuchs zwei Sternchen.

m = {"name": "ayato-p", "age": 24}

def g(name, age):
    return "name:" + name + ", age:" + str(age)

g(**m)
# -> 'name:ayato-p, age:24'

Wenden Sie die Funktion auf alle Elemente der Sequenz an und verwerfen Sie Null

(def people [{:name "ayato_p" :age 11}
             {:name "alea12" :age 10}
             {:name "zer0_u"}])

(remove nil? (map :age people)) ;(11 10)
(keep :age people) ;(11 10)

Verwenden Sie einfach die Listeneinschlussnotation mit dem bedingten Ausdruck.

people = [{":name": "ayato_p", ":age": 11},
          {":name": "alea12",  ":age": 10},
          {":name": "zer0_u"}]

[x[":age"] for x in people if ":age" in x]
# -> [11, 10]

Ich möchte wissen, ob ein Wert boolesch ist

Verwendung ist Instanz.

isinstance(True, bool) # -> True
isinstance(False, bool) # -> True
isinstance("", bool) # -> False
isinstance(None, bool) # -> False
isinstance(0, bool) # -> False
isinstance(1, bool) # -> False

Wenn unter mehreren Kandidaten ein Wert ungleich Null gefunden wird, wird der Wert zurückgegeben.

Dies gilt auch für Clojure und Python.

None or "ayato-p"
# -> "ayato-p"

Es gilt jedoch alles, was beim Boolen falsch wird (Keine, 0, Falsch, leere Liste usw.). Ich denke, es ist besser, es zu verwenden, wenn es ernst ist.

Ich möchte sehen, ob die Sequenz leer ist

Sie können die Länge mit len messen oder mit if bewerten, wie es ist. Wenn Sie es in bool einschließen, wird True / False abhängig vom Vorhandensein oder Fehlen des Inhalts zurückgegeben.

ev = []
v = [1, 2]

if ev:
    print("not empty")
else:
    print("empty")
# -> empty

if v:
    print("not empty")
else:
    print("empty")
# -> not empty

bool(ev)
# -> False
bool(v)
# -> True

Ich möchte nur dann zuordnen / dissoziieren, wenn die Bedingungen für die Karte erfüllt sind, und sie zurückgeben, wie es anders ist

(def m {:foo 1 :bar 2})

(cond-> m
  true (assoc :baz 3)) ;{:foo 1, :bar 2, :baz 3}

(cond-> m
  false (assoc :baz 3)) ;{:foo 1, :bar 2}

mit if und dict

m = {":foo": 1, ":bar": 2}

dict(m, **{":baz": 3}) if True else m
# -> {':bar': 2, ':baz': 3, ':foo': 1}

dict(m, **{":baz": 3}) if False else m
# -> {':bar': 2, ':foo': 1}

Dies ist das erste Mal, dass ich die Diktierfunktion auf diese Weise verwende. Wenn Sie tatsächlich ein Programm in Python schreiben, ist es meiner Meinung nach üblicher, den Inhalt von dict vor der Verwendung neu zu schreiben.

Ich möchte aufhören, in der Mitte zu reduzieren

(reduce (fn [acc x]
          (if (zero? x)
            (reduced 0)
            (* acc x)))
        1
        (cycle [9 8 7 6 5 4 3 2 1 0]))

Da Reduced nicht in Python enthalten ist, verwenden wir Ausnahmen, um ähnliche Funktionen zu implementieren.

import functools

class Reduced(Exception):
    def __init__(self, data):
        super().__init__()
        self.data = data

def myreduce(f, it):
    try:
        return functools.reduce(f, it)
    except Reduced as e:
        return e.data

def mymultiply(acc, x):
    if x == 0:
        raise Reduced(0)
    return acc * x

myreduce(mymultiply, [9, 8, 7, 6, 5, 4, 3, 2, 1, 0])
# -> 0

Ich möchte eine Funktion (Karte) auf alle Tasten (Werte) einer Karte anwenden

Einfach, wenn Sie die Wörterbucheinschlussnotation verwenden.

m = {"key1": 1,
     "key2": 2,
     "key3": 3}

{":" + k: v for k, v in m.items()}
# -> {':key1': 1, ':key2': 2, ':key3': 3}

Ich möchte Elemente aus einem Vektor löschen, der auf einem Index basiert

Wenn Sie die Daten in der Liste ändern möchten, können Sie pop verwenden. Sie können auch eine neue Liste mit der Aufzählungs- und Listeneinschlussnotation erstellen.

l = [9, 8, 7, 6, 5, 4, 3, 2, 1]
l.pop(5)
l
# -> [9, 8, 7, 6, 5, 3, 2, 1]

l = [9, 8, 7, 6, 5, 4, 3, 2, 1]
[x for i, x in enumerate(l) if i != 5]
# -> [9, 8, 7, 6, 5, 3, 2, 1]

Ich möchte eine Instanz von java.util.LinkedList zu einem Vektor machen

Normales Python kann keine Java-Instanzen verarbeiten. In Java scheint ein Python namens Jython implementiert zu sein, aber die Entwicklung scheint zu stagnieren. Überspringen Sie es also.

Ich möchte einen Wert behalten, der zwischen den Schleifen mehrmals aktualisiert wird

Dies ist normalerweise eine for-Schleife.

Ich möchte eine einfache Datenbank, auf die im gesamten Programm verwiesen werden kann

Überspringen Sie es, weil die Quelle sagt "Ich empfehle es nicht sehr".

Entfernen Sie falsche Werte aus der Liste

(filter identity [nil false true 1 "hello" [1 2] {:foo 1} :hoge])
;; (true 1 "hello" [1 2] {:foo 1} :hoge)

Dies ist auch eine Listeneinschlussnotation

[x for x in [None, False, True, 1, "hello", [1, 2], {":foo": 1}] if x]
# -> [True, 1, 'hello', [1, 2], {':foo': 1}]

Indizieren Sie die Liste der Objekte

Wie bereits oben erwähnt, werden wir enumerate verwenden.

list(enumerate(["a", "b", "c", "d", "e"]))
# -> [(0, 'a'), (1, 'b'), (2, 'c'), (3, 'd'), (4, 'e')]

Auf diese Weise können Sie es wie folgt verwenden.

[str(i) + " is " + x for i, x in enumerate(["a", "b", "c", "d", "e"])]
# -> ['0 is a', '1 is b', '2 is c', '3 is d', '4 is e']

Holen Sie sich die erste, die der Bedingung entspricht, aus der Sequenz

(defn find-first [pred coll]
  (first (drop-while (complement pred) coll)))

Es scheint, als sollten Sie eine schlampige for-Schleife schreiben, aber ich werde sie nicht schreiben! !! Erstellen Sie einen Generator und verwenden Sie next, um das erste Element abzurufen.

l = [1, 2, 3, 4, 5, 6, 7, 8, 9]
next(x for x in l if x > 4)
# -> 5

Ein Beispiel für das Extrahieren der kleinsten Primzahl, die größer als eine bestimmte natürliche Zahl ist, durch Versuchsteilung

import itertools

def isprime(x):
    return next((0 for n in range(2, int(x ** 0.5) + 1)
                                         if x % n == 0), 1)

next(x for x in itertools.count(1000) if isprime(x))
# -> 1009

(Hinzugefügt am 20. Juli 2017) Es ist prägnanter, "all" zu verwenden, was true zurückgibt, wenn alle Elemente von iterable im primären Urteil wahr sind.

def isprime(x):
    return all(x % n for n in range(2, int(x ** 0.5) + 1))

Zusammenfassung

Können Sie uns einen schnellen Vergleich zwischen Clojure und Python geben? Da ich ein Anfänger von Clojure bin, kann Clojure viele Dinge tun, Python jedoch nicht.

Wenn Sie es jedoch so betrachten, können Sie sehen, dass es in Python mithilfe der Listeneinschlussnotation und der Generatorausdrücke möglich ist, eine funktionale sprachähnliche Verarbeitung sehr kompakt zu schreiben, ohne zusätzliche Funktionsnamen zu schreiben.

Sie müssen sich nicht zwingen, den Generator wie im letzten Beispiel zu verwenden, aber wenn Sie ihn so weit betrachten, dass Sie so etwas tun können, kann es Ihnen helfen, eines Tages Code zu schreiben.

Bis bald ~.

Recommended Posts

Ich habe eine funktionale Sprache mit Python ausprobiert
Ich habe fp-Wachstum mit Python versucht
Ich habe versucht, mit Python zu kratzen
Ich habe gRPC mit Python ausprobiert
Ich habe versucht, mit Python zu kratzen
Ich habe versucht, WebScraping mit Python.
Ich habe mit Python eine Lotterie gemacht.
Ich habe versucht, Prolog mit Python 3.8.2 auszuführen.
Ich habe mit Python einen Daemon erstellt
Ich habe die SMTP-Kommunikation mit Python versucht
Ich habe versucht, die Wahrscheinlichkeit eines Bingospiels mit Python zu simulieren
Ich habe versucht, in einem tief erlernten Sprachmodell zu schreiben
Ich habe mit Python einen Zeichenzähler erstellt
Ich habe eine Heatmap mit Seaborn [Python] gezeichnet.
Ich habe versucht, mit Python + opencv nicht realistisch zu rendern
Ich habe versucht, mit Python ② (Fibonacci-Zahlenfolge) aufzuklären.
Was ich mit Python-Arrays gemacht habe
Ich habe mit Python eine Hex-Map erstellt
Ich habe versucht, natürliche Sprache mit Transformatoren zu verarbeiten.
Ich habe mit Python ein schurkenhaftes Spiel gemacht
Ich habe mit Python einen einfachen Blackjack gemacht
Ich habe mit Python eine Einstellungsdatei erstellt
# Ich habe so etwas wie Vlookup mit Python # 2 ausprobiert
Ich habe mit Python einen Neuronensimulator erstellt
[5.] Ich habe versucht, mit Python ein bestimmtes Authenticator-ähnliches Tool zu erstellen
[2nd] Ich habe versucht, mit Python ein bestimmtes Authenticator-ähnliches Tool zu erstellen
[3.] Ich habe versucht, mit Python ein bestimmtes Authenticator-ähnliches Tool zu erstellen
[Python] Ein Memo, das ich versucht habe, mit Asyncio zu beginnen
Ich habe versucht, mit Python eine Liste von Primzahlen zu erstellen
Ich habe versucht, mit Selenium und Python einen regelmäßigen Ausführungsprozess durchzuführen
Ich habe versucht, mit Python eine 2-Kanal-Post-Benachrichtigungsanwendung zu erstellen
Ich habe versucht, eine ToDo-App mit einer Flasche mit Python zu erstellen
[4.] Ich habe versucht, mit Python ein bestimmtes Authenticator-ähnliches Tool zu erstellen
[1.] Ich habe versucht, mit Python ein bestimmtes Authenticator-ähnliches Tool zu erstellen
Ich habe Python> Decorator ausprobiert
Ich habe versucht, das Bild mit Python + OpenCV zu "glätten"
Ich habe Hunderte Millionen SQLite mit Python ausprobiert
Ich habe eine GUI-App mit Python + PyQt5 erstellt
Ich habe versucht, das Bild mit Python + OpenCV zu "differenzieren"
Ich habe versucht, mit Python ein Tippspiel zu spielen
Ich habe versucht, mit Python einen Twitter-Blocker für faule Mädchen zu machen
Ich habe L-Chika mit Razpai 4 (Python Edition) ausprobiert.
[Python] Ich habe mit der Verarbeitung natürlicher Sprache ~ Transformatoren ~ gespielt
[Python] Ich habe mit Tkinter einen Youtube Downloader erstellt.
Ich habe Jacobian und teilweise Differenzierung mit Python versucht
Ich habe versucht, CloudWatch-Daten mit Python abzurufen
Ich habe versucht, Mecab mit Python2.7, Ruby2.3, PHP7 zu verwenden
Ich habe Funktionssynthese und Curry mit Python versucht
Ich habe versucht, LLVM IR mit Python auszugeben
Ich habe versucht, das Bild mit Python + OpenCV zu "binarisieren"
Ich habe versucht, Pythonect, eine Programmiersprache für den Datenfluss, zu verwenden.
Ich habe versucht, eine CSV-Datei mit Python zu lesen
Ich habe versucht, mit Python Faiss zu laufen, Go, Rust
Ich habe versucht, die Herstellung von Sushi mit Python zu automatisieren