[Feature Poem] Ich verstehe die funktionale Sprache nicht. Sie können sie mit Python verstehen: Teil 1 Funktionen, die Funktionen empfangen, sind praktisch.

Dies ist ein ** Feature-Gedicht **, das die Funktionen der funktionalen Programmierung in Python beschreibt. IQ145 schönes Mädchen wird nicht herauskommen, also bitte nicht zu viel erwarten.

[Zielgruppe Leser]

[Serienartikel]

Einführung

Es gibt einen Satz "Warum Funktionsprogrammierung wichtig ist". Wie der Titel schon sagt, ist es ein Satz, der einführt, wie nützlich eine funktionale Sprache ist. Es ist lang, aber es sieht in drei Zeilen so aus:

Obwohl dieser Satz und dieser Inhalt hoch bewertet werden, ** wird die Güte der Funktionssprache durch den Code der Funktionssprache erklärt, sodass er nicht an Benutzer übertragen wird, die die Funktionssprache überhaupt nicht kennen **. Ich habe ein Problem.

Wenn Sie jemandem erklären, der keine funktionalen Sprachen beherrscht, warum sollten Sie versuchen, nur funktionale Sprachen zu erklären (ich wünschte, ich hätte den Code auch für andere beliebte Sprachen geschrieben)? Es ist genau wie "** Wenn Sie die technischen Begriffe nicht verstehen und den Programmierer fragen, werden sie in schwierigeren technischen Begriffen erklärt **". Selbst wenn Sie die funktionale Sprache kennen und diesen Satz lesen möchten, haben Sie nur den Eindruck, dass die funktionale Sprache schwierig ist.

Daher werden in diesem Gedicht "Funktionen höherer Ordnung" und "verzögerte Auswertung", die in "Warum Funktionsprogrammierung wichtig ist" als besonders wichtig angesehen werden, in Python erläutert. Ich werde es erklären, ohne den Code der funktionalen Sprache zu verwenden, damit es für Leute, die keine Benutzer der funktionalen Sprache sind, leicht zu verstehen ist.

(Hey, da! Sag nicht "Japanische Python-Benutzer sind weniger als funktionale Sprachbenutzer, oder?")

Vorbereitung zur Erklärung von Funktionen höherer Ordnung

Es ist eine große Hürde, Funktionen höherer Ordnung plötzlich zu erklären. Bereiten wir uns also vorher vor.

Funktionsobjekt

In Python sind ** Funktionen Objekte **.

Der tatsächliche Status der ** Funktionsdefinition wie folgt ist beispielsweise die Operation ** "Erstellen eines Funktionsobjekts und Zuweisen zu einer Variablen".

##Ein Funktionsobjekt wird erstellt und der Variablen Hallo zugeordnet
def hello(name):
  print("Hello %s!" % name)

##Wenn Sie sich den Inhalt der Variablen Hallo ansehen, können Sie sehen, dass es sich um ein Funktionsobjekt handelt.
print(hello)    #Ausführungsergebnis:<function hello at 0x1007a3ed8>

Daher können Sie die Funktion aufrufen, indem Sie den Inhalt der Variablen "Hallo" einer anderen Variablen zuweisen.

##Der Inhalt der Variablen Hallo kann einer anderen Variablen zugewiesen und aufgerufen werden.
say = hello     #Weisen Sie das Funktionsobjekt einer anderen Variablen zu
say("world")    #Nennen(Das Ergebnis ist Hallo("world")Gleich wie)

Zusätzlich zu def können Sie mit lambda auch Funktionsobjekte erstellen. Der Unterschied zwischen den beiden ist wie folgt:

##Die durch def definierte Funktion ist
def add(x, y):
  return x + y
print(add(3, 5))      #=> 8

##Sie können auch mit Lambda schreiben(Allerdings nur bei einer einzigen Formel)
add = lambda x, y: x + y    #Sie müssen keine Rücksendung schreiben
print(add(3, 5))      #=> 8

##def enthält mehrere Anweisungen, muss jedoch unabhängige und einzelne Anweisungen sein
def sum(numbers):
  t = 0                 #Diese Funktion enthält also mehrere Anweisungen
  for n in numbers:     #Kann nicht mit Lambda schreiben
    t += n
  return t

##Lambda kann nur ein einzelner Ausdruck sein, aber es kann in andere Anweisungen und Ausdrücke eingebettet werden
sorted(strings, lambda s: len(s))  #Beispiel für die Einbettung von Lambda in ein Funktionsargument

Wichtig ist, dass Funktionen in Python Objekte sind, sodass Sie sie wie Ganzzahlen und Zeichenfolgen als Daten ** behandeln können. Da Sie die Funktion als Daten behandeln können, können Sie Folgendes tun:

##Funktionen können als Daten behandelt werden (als wären sie Ganzzahlen oder Zeichenfolgen).
n = 123       #Weisen Sie einer Variablen eine Ganzzahl zu
s = "ABC"     #Weisen Sie einer Variablen eine Zeichenfolge zu
f = hello     #Weisen Sie einer Variablen eine Funktion zu

##Übergeben Sie eine Funktion als Argument an eine andere Funktion
otherfunc(hello)

##Erstellen Sie eine neue Funktion innerhalb einer Funktion und geben Sie sie zurück
def create_func():
  def add(x, y):
    return x + y
  return add
  ##Oder das ist in Ordnung
  #return lambda x, y: x + y

Zusammenfassung hier:

Was die Funktion darstellt

Selbst wenn Sie kurz "Funktion" sagen, gibt es verschiedene Inhalte, die es darstellt. Hier habe ich versucht, sie in die folgenden drei zu klassifizieren.

** (A) Berechnungsformel / Umrechnungsformel **… Berechnet einen Wert zum anderen. Oder konvertieren Sie einen Wert in einen anderen.

##Berechnen Sie den doppelten Wert(In doppelten Wert konvertieren)
def double(x):
  return x * 2

##Berechnen Sie die Summe der Argumente(In Summe von Argumenten konvertieren)
def add(x, y):
  return x + y

##Berechnen Sie den Namen der HTML-Klasse anhand der Zeilennummer(Konvertieren Sie Zeilennummern in HTML-Klassennamen)
def classname(index):
  if index % 2 == 0:
    return "row-even"
  else:
    return "row-odd"

** (B) Bedingter Ausdruck / Beurteilungsausdruck **… Beurteilt, ob der Wert die Bedingung erfüllt. Gibt true zurück, wenn zufrieden, false, wenn nicht zufrieden. (Hinweis: Python verwendet "True" / "False" anstelle von "true" / "false".)

##Bestimmen Sie, ob es gerade ist
def is_even(n):
  return n % 2 == 0    #Richtig für gerade, Falsch für ungerade

##Stellen Sie fest, ob es leer ist
def is_blank(line):
  if not line:         #Gibt True zurück, wenn None oder eine leere Zeichenfolge
    return True
  if not line.strip(): #Gibt True zurück, wenn nur Leerzeichen oder Zeilenvorschubzeichen verwendet werden
    return True
  return False         #Andernfalls wird False zurückgegeben

##Ob sie Liebhaber sind oder nicht(Nach Teketou)Richter
couples = [
  ("Kirito", "Asuna"),
  ("Mutig",   "Teufel"),
  ("Naruto", "Hinata"),
  ("Ellen", "Mikasa"),   #Einspruch wird nicht anerkannt
  ("Bruder", "Tiefer Schnee"),
  ("Kyon", "Sasaki"),   #Ich gebe den Einwand zu
]
def is_couple(boy, girl):
  return (boy, girl) in couples

** (C) Verarbeitung / Prozedur **… Eine Zeichenfolge ausgeben, eine Datei lesen usw.

##Prozess zum Anzeigen des Namens
def hello(name):
  print("Hello %s!" % name)

##Verarbeitung zum Lesen einer Datei und Zählen der Anzahl der Zeilen
## (Hinweis: Die with-Anweisung schließt die geöffnete Datei automatisch)
def count_lines(filename):
  n = 0
  with open(filename) as f:
    for line in f:
      n += 1
  print("%s lines" % n)

Diese Klassifizierung ist jedoch nicht streng. Bitte beachten Sie, dass dies nur eine grobe Klassifizierung zur Verwendung in den folgenden Erläuterungen ist.

Auch ich möchte die Nebenwirkungen hier wirklich erklären, aber wenn ich sage "Was sind die Nebenwirkungen?", Übersteigt dies den Rahmen dieses Gedichts und die Fähigkeit des Autors, daher werde ich die Erklärung hier weglassen (ich liebe solche Fachbegriffe). Kluge Leute werden es tun).

Zusammenfassung hier:

Rolle von Argumenten in Funktionen / Prozeduren / Unterprogrammen

Erstellen wir beispielsweise eine "Funktion, die 1 bis 10 summiert". (Hinweis: range (1, 11) erzeugt eine ganze Zahl von 1 bis 10, nicht bis zu 11.)

def total():
  t = 0
  for i in range(1, 10+1):
    t += i
  return t

Es ist zu einfach.

Normalerweise würden Sie dies jedoch nicht schreiben und Argumente verwenden, um daraus eine "Funktion zu machen, die 1 bis n summiert".

def total(n):
  t = 0
  for i in range(1, n+1):
    t += i
  return t

Sie können auch "eine Funktion verwenden, die m zu n summiert".

def total(m, n):    #Argumentprüfung weggelassen
  t = 0
  for i in range(m, n+1):
    t += i
  return t

Betrachtet man das:

Auf diese Weise können Sie einen variablen Teil ** erstellen (oder erhöhen), indem Sie ** Argumente in Funktionen / Prozeduren / Unterprogrammen verwenden (ungefähr, aber wenn Sie die Template-Engine kennen, denke ich, dass es ähnlich ist. Ist es nicht?). Je variabler die Teile sind, desto breiter ist der Anwendungsbereich.

Und wenn Sie nicht nur Daten wie numerische Werte, Zeichenfolgen, Boolesche Werte und Arrays, sondern auch ** Berechnungsformeln / Konvertierungsformeln, bedingte Formeln / Beurteilungsformeln und Verarbeitung / Prozeduren an den variablen Teil der Funktion übergeben, wird der Anwendungsbereich weiter erweitert. Ausbreitung **. Sie können dies mit einem Funktionsobjekt tun.

Über Funktionen, die Funktionen empfangen (Funktionen höherer Ordnung)

Funktionen höherer Ordnung sind Funktionen, die die Funktion als Daten behandeln. Im Einzelnen sieht es so aus:

(Natürlich ist "eine Funktion, die eine Funktion empfängt und eine Funktion zurückgibt" auch eine Funktion höherer Ordnung.)

Von diesen beschreibt dieses Gedicht die erste "Funktion, die eine Funktion erhält".

Funktionen höherer Ordnung, die Funktionen empfangen, können grob wie folgt klassifiziert werden.

Schauen wir uns diese mit konkreten Beispielen an.

Funktionen höherer Ordnung, die Formeln / Konvertierungsformeln erhalten

Schauen Sie sich den folgenden Code an. Die beiden Funktionen machen unterschiedliche Dinge.

##Eine Funktion, die ein Array von Ganzzahlen verwendet und jedes Element verdoppelt
def doubles(arr):
  newarr = []
  for x in arr:
    newarr.append(x * 2)      #Verdoppeln Sie jedes Element
  return newarr

##Eine Funktion, die ein Array von Zeichenfolgen verwendet, jedes Element in Großbuchstaben konvertiert und zurückgibt
def uppers(arr):
  newarr = []
  for x in arr:
    newarr.append(x.upper())  #Großschreibung jedes Elements
  return newarr

(Hinweis: In Python wird es als "Liste" anstelle eines "Arrays" bezeichnet. Es wird als "Liste" bezeichnet, es handelt sich jedoch nicht um eine verkettete Liste, sondern um ein Array variabler Länge in anderen Sprachen (Java java.util.ArrayList und Ruby). Array). Bitte beachten Sie, dass dieses Gedicht nicht dazu gedacht ist, Python zu erklären. Wir wagen es daher, es unter Berücksichtigung anderer Sprachbenutzer "Array" zu nennen.)

Nun machen die beiden Funktionen verschiedene Dinge, aber sie machen sehr ähnliche Dinge. ** Der einzige Unterschied ist die Formel / Konvertierungsformel, die an newarr.append () ** übergeben wird.

Daher werden wir den gemeinsamen Teil in eine Funktion namens "map ()" verwandeln und den anderen Teil als Funktion übergeben:

##Formel für jedes Element des Arrays/Funktion zum Anwenden der Konvertierungsformel
def map(func, arr):
  newarr = []
  for x in arr:
    newarr.append(func(x))      #Berechnungsformel für jedes Element/Wenden Sie die Umrechnungsformel an
  return newarr

##Eine Funktion, die ein Array von Ganzzahlen verwendet und jedes Element verdoppelt
def doubles(arr):
  def func(x): return x * 2     #eine Formel/Unter Verwendung der Umrechnungsformel
  return map(func, arr)         #Rufen Sie eine gemeinsame Funktion auf
  ##Oder
  #return map(lambda x: x * 2, arr)

##Eine Funktion, die ein Array von Zeichenfolgen verwendet, jedes Element in Großbuchstaben konvertiert und zurückgibt
def uppers(arr):
  def func(x): return x.upper() #eine Formel/Unter Verwendung der Umrechnungsformel
  return map(func, arr)         #Rufen Sie eine gemeinsame Funktion auf
  ##Oder
  #return map(lambda x: x.upper(), arr)

Somit ist "map ()" eine "Funktion höherer Ordnung, die eine Berechnungs- / Umrechnungsformel als Funktion erhält". Durch die Verwendung von Funktionen höherer Ordnung wie "map ()" kann auch eine gemeinsame Verarbeitung erstellt und der Code vereinfacht werden.

Zusammenfassung hier:

Beachten Sie, dass in Python "map ()" standardmäßig integriert ist, sodass Sie es nicht selbst definieren müssen. Auch Pythons map () kann nicht nur für Arrays, sondern auch für Strings und Dateien verwendet werden, aber das ist nicht der Zweck dieses Gedichts, also werde ich es weglassen.

Funktion höherer Ordnung, die Bedingungs- / Beurteilungsausdrücke empfängt

Schauen Sie sich den folgenden Code an. Die beiden Funktionen machen unterschiedliche Dinge.

##Eine Funktion, die ein Array von Ganzzahlen verwendet und nur gerade Zahlen auswählt und zurückgibt
def evens(arr):
  newarr = []
  for x in arr:
    if x % 2 == 0:           #Wähle nur gerade
      newarr.append(x)
  return newarr

##Empfängt eine Reihe von Zeichenfolgen und Enden".html"Eine Funktion, die nur diejenigen auswählt, die es sind
def shorts(arr):
  newarr = []
  for x in arr:
    if x.endswith(".html"):  #Das Ende ist".html"Wählen Sie, was ist
      newarr.append(x)
  return newarr

(Hinweis: In Python heißt es "Liste" anstelle von "Array". Beachten Sie jedoch, dass dieses Gedicht unter Berücksichtigung anderer Benutzer absichtlich "Array" genannt wird.)

Diese beiden Funktionen machen auch verschiedene Dinge, aber sie machen sehr ähnliche Dinge. ** Der einzige Unterschied ist der in der if-Anweisung angegebene bedingte Ausdruck / Beurteilungsausdruck **.

Daher ist der gemeinsame Teil eine Funktion namens "filter ()", und der andere Teil wird als Funktion übergeben:

##Bedingter Ausdruck von jedem Element des Arrays/Eine Funktion, die nur diejenigen auswählt und zurückgibt, die die Beurteilungsformel erfüllen
def filter(func, arr):
  newarr = []
  for x in arr:
    if func(x):             #Bedingter Ausdruck/Wählen Sie nur die Elemente aus, die der Beurteilungsformel entsprechen
      newarr.append(x)
  return newarr

##Eine Funktion, die ein Array von Ganzzahlen verwendet und nur gerade Zahlen auswählt und zurückgibt
def evens(arr):
  def func(x): return x % 2 == 0    #Bedingter Ausdruck/Machen Sie die Beurteilungsformel zu einer Funktion
  return filter(func, arr)          #Rufen Sie eine gemeinsame Funktion auf
  ##Oder
  #return filter(lambda x: x % 2 == 0, arr)

##Empfängt eine Reihe von Zeichenfolgen und Enden".html"Eine Funktion, die nur diejenigen auswählt, die es sind
def htmls(arr):
  def func(x): return x.endswith(".html")  #Bedingter Ausdruck/Machen Sie die Beurteilungsformel zu einer Funktion
  return filter(func, arr)                 #Rufen Sie eine gemeinsame Funktion auf
  ##Oder
  #return filter(lambda x: x.endswith(".html"), arr)

Somit ist "filter ()" eine "Funktion höherer Ordnung, die Bedingungs- / Beurteilungsausdrücke als Funktionen empfängt". Und ich konnte den Code vereinfachen, indem ich Funktionen höherer Ordnung wie filter () verwendete.

Zusammenfassung hier:

Beachten Sie, dass Python standardmäßig auch filter () bereitstellt, sodass Sie es nicht selbst definieren müssen. Der Python-Standard filter () kann nicht nur für Arrays, sondern auch für Zeichenketten und Dateien verwendet werden, liegt jedoch außerhalb des Geltungsbereichs dieses Gedichts, sodass die Erklärung weggelassen wird.

Funktion höherer Ordnung, die die Verarbeitung / Prozedur erhält

Schauen Sie sich den folgenden Code an. Mit den beiden Funktionen führen wir separate Benchmarks durch.

## (Für Python 3)
try:
  xrange
except NameError:
  xrange = range

N = 1000000

import time

## str.join()Benchmark der String-Verkettung mit
def bench_strjoin():
  start = time.time()
  for _ in xrange(N):
    s = str.join("", ("Haruhi", "Kyon", "Mikuru", "Itsuki", "Yuki"))
  end = time.time()
  print("%.3f sec" % (end - start))

## '%'Benchant für die Verkettung von Zeichenfolgen mithilfe von Operatoren
def bench_percentop():
  start = time.time()
  for _ in xrange(N):
    s = "%s%s%s%s%s" % ("Haruhi", "Kyon", "Mikuru", "Itsuki", "Yuki")
  end = time.time()
  print("%.3f sec" % (end - start))

(Hinweis: In Python wird bei Verwendung von "str.join ()" häufig "" geschrieben. Join ((...)) ".

## ()
try:
  xrange
except NameError:
  xrange = range

N = 1000000

import time

##Wenn wir uns diese beiden Funktionen ansehen, können wir Folgendes sehen: * Der Prozess zum Messen der Ausführungszeit ist üblich. * Der Inhalt der Benchmarks ist nicht üblich. Definieren Sie daher eine Funktion namens "Benchmark ()", die den Benchmark misst, und übergeben Sie den Inhalt (die Verarbeitung) des Benchmarks als Funktion. Dann sieht der Code folgendermaßen aus: Eine Funktion, die die Ausführungszeit für Python 3 misst und anzeigt
def benchmark(func):
  start = time.time()
  func()               #Rufen Sie den Benchmark-Prozess auf
  end = time.time()
  print("%.3f sec" % (end - start))

## str.join()Benchmark der String-Verkettung mit
def bench_strjoin():
  def func():
    for _ in xrange(N):
      s = str.join("", ("Haruhi", "Kyon", "Mikuru", "Itsuki", "Yuki"))
  benchmark(func)

## '%'Benchant für die Verkettung von Zeichenfolgen mithilfe von Operatoren
def bench_percentop():
  def func():
    for _ in xrange(N):
      s = "%s%s%s%s%s" % ("Haruhi", "Kyon", "Mikuru", "Itsuki", "Yuki")
  benchmark(func)

##Hinweis: für Statement Benchmark()Einschließlich in func()Anrufkosten
##Ich mache das hier nicht, weil es nicht ignoriert werden kann.

Somit ist "Benchmark ()" eine "Funktion höherer Ordnung, die einen Prozess / eine Prozedur als Funktion empfängt". Dank der Funktionen höherer Ordnung konnten wir gemeinsame Prozesse herausziehen und den Code vereinfachen.

Um dies etwas weiter zu verallgemeinern, kann gesagt werden, dass "** Vorverarbeitung und Nachbearbeitung durch Verwendung von Funktionen höherer Ordnung ** hinzugefügt werden können". Zum Beispiel:

Dies wird berücksichtigt.

Zusammenfassung hier:

Wenn Sie Vor- und Nachbearbeitung hinzufügen möchten, verwenden Sie in Python häufig die with-Anweisung, anstatt Funktionen höherer Ordnung (später beschrieben) zu verwenden.

Funktionen höherer Ordnung, die sowohl in Formeln als auch in Prozessen empfangen werden

Schauen Sie sich den folgenden Code an. Die beiden Funktionen machen unterschiedliche Dinge.

##Eine Funktion, die ein Array von Ganzzahlen verwendet und eine Summe zurückgibt
def sum(arr):
  t = 0            #Anfangswert: 0
  for x in arr:
    t = t + x      #Berechnen Sie die Summe(Zur späteren Erklärung t+=Nicht x)
  return t

##Eine Funktion, die ein Array von Zeichenfolgen empfängt, in ein Wörterbuch konvertiert und zurückgibt.
def to_dict(arr):
  t = {}           #Anfangswert: Leeres Wörterbuch
  for x in arr:
    t[x] = x       #In Wörterbuch konvertieren
    t = t          #Dies ist im Wesentlichen nicht erforderlich, wird jedoch zur Erläuterung hinzugefügt
  return t

(Hinweis: Das "Wörterbuch" in Python entspricht "Hash" in Ruby und "java.util.HashMap" in Java.)

Diese beiden Funktionen machen auch verschiedene Dinge, aber sie machen sehr ähnliche Dinge. ** Der einzige Unterschied ist der Anfangswert und die Formeln und Prozesse in der Schleife **.

Daher werden die Berechnungsformeln und die Verarbeitung in der Schleife zu Funktionen gemacht. Dann kann der gemeinsame Teil wie folgt in eine Funktion namens "redu ()" extrahiert werden:

##Führen Sie einige Berechnungen oder Verarbeitungen für jedes Element des Arrays durch und geben Sie die gestapelten Ergebnisse zurück
def reduce(func, arr, initial):
  t = initial         #Ursprünglicher Wert
  for x in arr:
    t = func(t, x)    #Berechnungen und Verarbeitung durchführen
  return t

##Eine Funktion, die ein Array von Ganzzahlen verwendet und eine Summe zurückgibt
def sum(arr):
  def func(t, x): return t + x      #Machen Sie die Formel zu einer Funktion
  return reduce(func, arr, 0)       #Rufen Sie eine gemeinsame Funktion auf
  ##Oder
  #return reduce(lambda t, x: t + x, arr, 0)

##Eine Funktion, die ein Array von Zeichenfolgen empfängt, in ein Wörterbuch konvertiert und zurückgibt.
def to_dict(arr):
  def func(t, x):                   #Machen Sie die Verarbeitung zu einer Funktion
    t[x] = x
    return t
  return reduce(func, arr, {})      #Rufen Sie eine gemeinsame Funktion auf

Auf diese Weise ist "redu ()" eine "Funktion höherer Ordnung, die Formeln empfängt und als Funktionen verarbeitet". Auf den ersten Blick sollten "Berechnen der Summe" und "Konvertieren in ein Wörterbuch" völlig unterschiedliche Prozesse sein, aber ich finde es nicht sehr interessant, dass Sie "redu ()" verwenden können, um gemeinsame Teile zu erstellen. Ist es?

Übrigens war der Anfangswert für "redu ()" in der obigen Definition erforderlich. Im Allgemeinen kann redu () jedoch den Anfangswert weglassen. In diesem Fall wird das erste Element als Anfangswert verwendet. Der Code sieht folgendermaßen aus:

class Undefined(object):
  pass           #Python-Pass bedeutet "nichts tun"
undefined = Undefined()

def reduce(func, arr, initial=undefined):
  ##Wenn kein Anfangswert angegeben ist, verwenden Sie stattdessen das erste Element
  if initial is undefined:   # 'is'Ist'=='Ich denke, es ist eine strengere Version von!
    t = undefined
    for x in arr:
      if t is undefined:
        t = x
      else:
        t = func(t, x)
    ##Wenn das Array jedoch leer ist, tritt ein Fehler auf(Weil der Rückgabewert undefiniert ist)
    if t is undefined:
      raise TypeError("reduce() of empty sequence with no initial value")
    return t
  ##Wenn der Anfangswert angegeben ist, wird er wie zuvor fortgesetzt
  else:
    t = initial
    for x in arr:
      t = func(t, x)
    return t

##Hinweis:`t = initial`Wann`return t`Kann leicht aus der if-Anweisung entfernt werden.
##Ich möchte dem leichteren Verständnis für Anfänger Priorität einräumen, also lass es so wie es ist.

In diesem Fall kann "sum ()" wie folgt geschrieben werden (mit unterschiedlichen Argumentnamen), wobei der Anfangswert weggelassen wird.

def sum(arr):
  return reduce(lambda a, b: a + b, arr)

Wenn Sie dies schreiben, ** kann der Operator "+", der zwei Argumente akzeptiert, so betrachtet werden, als ob er n Argumente akzeptiert **.

reduce()を使うと二項演算子があたかもn項演算子のように見える

Natürlich wiederholt der Inhalt von redu () nur den Operator "+", der zwei Argumente viele Male akzeptiert, aber je nach Sichtweise wird der Operator, der n Argumente akzeptiert, nur einmal verwendet. Es ist interessant, dass es so aussieht.

Zusammenfassung hier:

Beachten Sie, dass Python standardmäßig auch "redu ()" bereitstellt und Sie es nicht selbst definieren müssen (obwohl Python 3 "von functools import reduct" erfordert).

Kombinieren Sie Funktionen höherer Ordnung

Funktionen höherer Ordnung sind für sich genommen bequem genug, in Kombination jedoch noch bequemer.

##Ausgabe von 1 bis 10(1 <= x < 10+1)
nums = range(1, 10+1)
for x in nums:
  print(x)

##Wählen Sie nur ungerade Zahlen von 1 bis 10 aus und geben Sie sie aus
nums = range(1, 10+1)
for x in filter(lambda x: x%2 == 1, nums):
  print(x)

##Wählen Sie nur ungerade Zahlen von 1 bis 10 und Quadrat und Ausgabe
nums = range(1, 10+1)
for x in map(lambda x: x*x, filter(lambda x: x%2 == 1, nums)):
  print(x)

##Wählen Sie nur ungerade Zahlen von 1 bis 10, Quadrat und Summe
from functools import reduce    # python3
nums = range(1, 10+1)
total = reduce(lambda t, x: t+x,
               map(lambda x: x*x, filter(lambda x: x%2 == 1, nums)))
print(total)

##Oder
from functools import reduce    # python3
nums = range(1, 10+1)                      #Von 1 bis 10
nums = filter(lambda x: x%2 == 1, nums)    #Wählen Sie nur ungerade Zahlen,
nums = map(lambda x: x*x, nums)            #Kariert
total = reduce(lambda t, x: t+x, nums)     #Summe
print(total)

Aber um ehrlich zu sein, ist Pythons "Lambda" nicht sehr einfach zu schreiben. Dies ist viel natürlicher in Ruby, Groovy und Scala zu schreiben.

##Ruby kann so natürlich schreiben
print (1..10).select {|x| x%2 == 1 }.map {|x| x*x }.reduce {|t,x| t+x }

Wenn Sie sich diesen Ruby-Code ansehen, können Sie leicht erkennen, wie der Prozess nacheinander abläuft.

Wenn Sie UNIX verwenden, werden Sie feststellen, dass dies der Pipe-Verarbeitung sehr ähnlich ist. Wenn Sie mit der Rohrbearbeitung vergleichen möchten, sollten Sie die Verzögerungsbewertung erläutern, aber lassen Sie mich dies zu einem späteren Zeitpunkt tun.

Schleife gegen Funktion höherer Ordnung

Ich werde den Code neu veröffentlichen, der die Funktionen höherer Ordnung kombiniert.

##Code, der Funktionen höherer Ordnung kombiniert
from functools import reduce    # python3
total = reduce(lambda t, x: t+x,
               map(lambda x: x*x, filter(lambda x: x%2 == 1, nums, 0)))
##Oder
nums = filter(lambda x: x%2 == 1, nums)    #Wählen Sie nur ungerade Zahlen,
nums = map(lambda x: x*x, nums)            #Kariert
total = reduce(lambda t, x: t+x, nums, 0)  #Summe

Ich habe versucht, dasselbe prozedural mit der for-Anweisung zu schreiben.

##Code, der prozedural mit der for-Anweisung geschrieben wurde
total = 0
for x in nums:
  if x%2 == 1:
    total += x*x

Egal wie Sie es betrachten, die for-Anweisung ist einfacher und verständlicher ...

Beim Vergleich dieser beiden Codes stellen wir Folgendes fest:

Prozedural geschriebener Code Code mit Funktionen höherer Ordnung
Schleifen, bedingte Verzweigungen und Formeln befinden sich in einem Block Die Verarbeitung ist in Funktionen unterteilt und diese werden kombiniert.
Behandeln Sie die Elemente des Arrays nacheinander Behandeln Sie das gesamte Array zusammen("Aus dem gesamten Array auswählen", "Das gesamte Array quadrieren", "Das gesamte Array summieren" usw.)
Schnell (weil es nur einmal wiederholt wird und keine Funktionsaufrufe verwendet) Der Betrieb ist langsam(Weil Schleifen dreimal effektiv für Filter, Zuordnung und Reduzierung benötigt werden und es viele Funktionsaufrufe gibt)

Von besonderer Bedeutung sind der erste und der zweite. In der funktionalen Programmierung ist dies die Art zu denken und Dinge zu betrachten.

Um den dritten Punkt zu ergänzen, ist die Kombination von Funktionen sicherlich langsamer als ich in einer Schleife geschrieben habe, aber ob diese Langsamkeit wichtig ist, ist eine andere Frage. Es gibt viel mehr Fälle, in denen der Benchmark langsamer ist, sich die Erfahrung jedoch nicht ändert oder der Geschwindigkeitsengpass in einem anderen Teil wie I / O liegt.

Schlechte Nachrichten

Leider werden Funktionen höherer Ordnung, die Funktionen empfangen, in Python nicht sehr häufig verwendet. Dies liegt daran, dass das, was Sie mit Funktionen höherer Ordnung schreiben können, oft auf andere Weise natürlicher geschrieben werden kann.

Zum Beispiel ist es natürlicher, "map ()" und "filter ()" im Verständnis zu schreiben.

## map()Ist
newarr = map(lambda x: x * x, arr)

##Sie können dies in Listeneinschlussnotation schreiben
newarr = [ x * x for x in arr ]

## filter()Ist
newarr = filter(lambda x: x % 2 == 0, arr)

##Sie können dies in Listeneinschlussnotation schreiben
newarr = [ x for x in arr if x % 2 == 0 ]

Die Lesbarkeit der Einschlüsse macht sich insbesondere beim Kombinieren von "map ()" und "filter ()" bemerkbar.

## map()Und filtern()Die Kombination von
newarr = map(lambda x: x * x, filter(lambda x: x % 2 == 0, arr))

##Sie können dies in Listeneinschlussnotation schreiben
newarr = [ x * x for x in arr if x % 2 == 0 ]

Für redu () können Sie die Funktion sum () verwenden, um den Gesamtwert zu berechnen, und Sie können die Einschlussnotation des Wörterbuchs verwenden, um ein Array von Zeichenfolgen in ein Wörterbuch zu konvertieren.

##Zum Beispiel ist dies
total = reduce(lambda t, x: t + x, arr, 0)

##Das ist besser, egal was du denkst
total = sum(arr)


##Zum Beispiel ist dies
def func(t, x):
  t[x] = x
  return t
dictionary = reduce(func, strings)

##Verwenden Sie besser die Wörterbucheinschlussnotation
dictionary = { x:x for x in strings }

Wenn Sie Vor- und Nachbearbeitung hinzufügen möchten, sollten Sie die with-Anweisung verwenden.

try:
  xrange                #Für Python2
except NameError:
  xrange = range        #Für Python3

N = 1000000

import time
from contextlib import contextmanager

@contextmanager         # '@'Ist ein Funktionsdekorateur(Kommentar zu einem späteren Zeitpunkt)
def benchmark():
  start = time.time()
  yield                 # 'yield'Ist für den Generator(Kommentar zu einem späteren Zeitpunkt)
  end = time.time()
  print("%.3f sec" % (end - start))

with benchmark():
  for _ in xrange(N):
    s = str.join("", ("Haruhi", "Kyon", "Mikuru", "Itsuki", "Yuki"))

with benchmark():
  for _ in xrange(N):
    s = "%s%s%s%s%s" % ("Haruhi", "Kyon", "Mikuru", "Itsuki", "Yuki")

Wie Sie sehen können, bietet Python viele nützliche Funktionen, sodass die Funktionen höherer Ordnung, die die Funktionen erhalten, weniger verwendet werden (überhaupt nicht, sortiert (arr, key = fn). ) And re (Muster, Fn, String)` etc.).

Insbesondere war "redu ()" eine in Python2 integrierte Funktion, die in Python3 jedoch nur durch Importieren aus einer Bibliothek verwendet werden kann. Dies ist de facto ein Downgrade, und wir können die Absicht erkennen, dass "in Python andere Mittel als" redu () "verwendet werden können".

Die Funktionen höherer Ordnung, die die Funktionen erzeugen, werden jedoch immer noch häufig verwendet. Dies wird im nächsten Gedicht erklärt.

Python-spezifische Geschichte

import operator

## '=='Entspricht einem Operator
operator.eq(1+1, 2)   #=> True

## '+'Entspricht einem Operator
operator.add(1, 2)    #=> 3

Übungen

Schreiben Sie eine Beispielantwort in den Kommentarbereich.

** [Problem 1] ** Definieren wir "map ()", "filter ()" und "redu ()" selbst.

** [Problem 2] ** Die Funktion "parse_version ()", die eine Versionsnummer wie "3.4.10" in ein Array von Ganzzahlen wie "[3, 4, 10]" konvertiert, ist "map". Definieren wir es mit () `. Wie benutzt man:

print(parse_version("3.4.10"))   #=> [3, 4, 10]

(Hinweis: Verwenden Sie "3.4.2" .split ("."), Um eine Zeichenfolge zu teilen, und "int (" 123 ")", um eine Zeichenfolge in eine Ganzzahl umzuwandeln.)

** [Problem 3] ** Verwenden wir filter (), um die Funktion grep () zu definieren, die nur diejenigen aus dem Array von Zeichenfolgen auswählt, die dem regulären Ausdruck entsprechen. Wie benutzt man:

arr = grep(r'\d+', ["ABC", "F102", "X10Y", "ZZZ"])
print(arr)   #=> ["F102", "X10Y"]

(Hinweis: Verwenden Sie für reguläre Ausdrücke import re; m = re.search (r '.. pattern ..', string).)

** [Problem 4] ** Definieren wir eine Funktion max_by (), die mitredu ()den Maximalwert der angegebenen Vergleichsmethode aus den Elementen des Arrays zurückgibt. Wie benutzt man:

members = [
  ("Haruhi", "C"),   #Haruhi ist C.
  ("Mikuru", "E"),   #Mikuru ist E.
  ("Yuki",   "A"),   #Yuki ist A.
]

def getvalue(x):     #Brüste zurückgeben
  return x[1]

##Wer hat die größten Brüste?
ret = max_by(getvalue, members)
print(ret)   #=> ("Mikuru", "E")

(Ergänzung 08.02.2015: Das Problem war falsch! Es tut mir leid!)

Zusammenfassung

Ich habe mit Python die Funktion höherer Ordnung erklärt, die die Funktion empfängt.

abschließend

Aufgrund der Popularität von Gedichten in funktionaler Sprache ziehen funktionale Sprachen mehr Aufmerksamkeit auf sich als je zuvor. Dies ist eine einmalige Gelegenheit, daher möchte ich diese Gelegenheit nutzen, um die funktionalen Sprachmerkmale von Python und Ruby zu fördern und ** die Interessen der Fischer ** zu verfolgen.

Recommended Posts

[Feature Poem] Ich verstehe die funktionale Sprache nicht. Sie können sie mit Python verstehen: Teil 1 Funktionen, die Funktionen empfangen, sind praktisch.
[Feature Poem] Ich verstehe die funktionale Sprache nicht. Sie können sie mit Python verstehen: Teil 2 Die Funktion, die die Funktion generiert, ist erstaunlich.
Python Erstellen von Funktionen, an die Sie sich später erinnern können
[Python] Ich verstehe nicht, was ich mit Tabelle [Schlüssel] [0] + = 1 mache
Einführung in Python, die auch Affen verstehen können (Teil 3)
Einführung in Python, die auch Affen verstehen können (Teil 1)
Einführung in Python, die auch Affen verstehen können (Teil 2)
Es scheint, dass Sie jetzt mit blueqat Torbücher schreiben können
Schreiben Sie Python nicht, wenn Sie es mit Python beschleunigen möchten
Ich habe ein Paket erstellt, das morphologische Analysegeräte mit Python vergleichen kann
Ich habe ein Shuffle gemacht, das mit Python zurückgesetzt (zurückgesetzt) werden kann