[PYTHON] Zusammenfassung, wie der Status mit mehreren Funktionen geteilt wird

Beim Programmieren möchte ich oft "den Status mit mehreren Funktionen teilen".

Derzeit ist es besser, aus verschiedenen Lösungen das Beste auszuwählen, als globale Variablen zu verwenden oder den Zeiger ohne nachzudenken weiterzuleiten.

Daher werde ich die Methode, den Zustand mit mehreren Funktionen zu teilen, zusammen mit den Vor- und Nachteilen zusammenfassen, so viel ich mir vorstellen kann.

Verwenden Sie Python als Beispielcode und Racket (eine Art Schema), wenn Sie nicht in Python schreiben können. weil ich mag.

Globale Variablen

state = "initial state"

def fuga0():
    #Ändern Sie nach Bezugnahme auf den Zustand
    global state
    print(f"fuga0: {state}")
    state = "another state"
    return "result of fuga0"

def fuga1():
    #Beziehen Sie sich auf den Zustand
    print(f"fuga1: {state}")

def hoge():
    print(fuga0())
    fuga1()
    print(f"last: {state}")

hoge()

Ergebnis (Folgendes wird weggelassen)


fuga0: initial state
result of fuga0
fuga1: another state
last: another state

Kein sehr empfohlener Schreibstil.

Schaufelrelaiszeiger

from dataclasses import dataclass
from typing import Any

#Ein Zeiger, an den dieser Typ weitergeleitet wird
@dataclass
class Box:
    value: Any

def fuga0(box):
    print(f"fuga0: {box.value}")
    box.value = "another state"
    return "result of fuga0"

def fuga1(box):
    print(f"fuga1: {box.value}")

def hoge(box):
    print(fuga0(box))
    fuga1(box)
    print(f"last: {box.value}")

b = Box("initial state")

hoge(b)

Im Falle einer Konstante sollte der Wert anstelle des Zeigers Bucket-Relaying sein.

Erhält den aktuellen Status als Argument und gibt den neuen Status als Rückgabewert zurück

Es handelt sich um einen sogenannten funktionalen Schreibstil, und der Status ändert sich im Code nicht.

def fuga0(state):
    print(f"fuga0: {state}")
    return "result of fuga0", "another state"

def fuga1(state):
    print(f"fuga1: {state}")

def hoge(state):
    result, new_state = fuga0(state)
    print(result)
    fuga1(new_state)
    print(f"last: {new_state}")

hoge("initial")

Objektorientierung

Eine Methode, die häufig in objektorientierten Sprachen verwendet wird. Legen Sie den Status fest, für den Sie eine Mitgliedsvariable freigeben möchten.

class Hoge:
    def __init__(self):
        self._state = "initial state"
    
    def _fuga0(self):
        print(f"fuga0: {self._state}")
        self._state = "another state"
        return "result of fuga0"
    
    def _fuga1(self):
        print(f"fuga0: {self._state}")
    
    def __call__(self):
        print(self._fuga0())
        self._fuga1()
        print(f"last: {self._state}")

hoge = Hoge()
hoge()

Schließung

Nah an objektorientiert.

def create_hoge():
    state = "initial"
    
    def fuga0():
        nonlocal state
        print(f"fuga0: {state}")
        state = "another state"
        return "result of fuga0"
    
    def fuga1():
        print(f"fuga1: {state}")
    
    def hoge():
        print(fuga0())
        fuga1()
        print(f"last: {state}")
    
    return hoge

create_hoge()()

Glocal Variable

Muster meiner Gedanken. Erstellen Sie eine Variable, die nur in mit verwendet werden kann. Siehe den Link für Details.

param.py


_param = None
_initialized = False

@contextmanager
def parametrize(data):
    global _param
    global _initialized
    before = _param
    before_initialized = _initialized
    _param = data
    _initialized = True
    try:
        yield
    finally:
        _param = before
        _initialized = before_initialized

def set_param(data):
    if _initialized:
        global _param
        _param = data
    else:
        raise RuntimeError
    
def get_param():
    if _initialized:
        return _param
    else:
        raise RuntimeError
from param import get_param, set_param, parametrize

def fuga0():
    print(f"fuga0: {get_param()}")
    set_param("another state")
    return "result of fuga0"

def fuga1():
    print(f"fuga0: {get_param()}")

def hoge():
    print(fuga0())
    fuga1()
    print(f"last: {get_param()}")

with parametrize("initial state"):
    hoge()

Staatsmonade

Was ist Monade? Was ist Staatsmonade? Bitte googeln Sie für so etwas.

Schreiben wir mit Racket. Ich bin mir ein wenig unsicher über die Implementierung von ...

;Definition der Staatsmonade von hier
(require (prefix-in base: racket/base))
(require data/functor)
(require data/applicative)
(require data/monad)

(struct result (value state) #:transparent)

(struct state (f)
  #:methods gen:functor
  [(define (map g x)
     (state (λ (s)
              (match-define (result v ss) (run x s))
              (result (g v) ss))))]
  #:methods gen:applicative
  [(define (pure _ x)
     (state (λ (s) (result x s))))
   (define (apply f xs)
     (define (get-args xs s)
       (match xs
         [(cons x rest)
          (match-define (result xv xs) (run x s))
          (match-define (result args argss) (get-args rest xs))
          (result (cons xv args) argss)]
         [_ (result `() s)]))
     (state (λ (s)
              (match-define (result fv fs) (run f s))
              (match-define (result args argss) (get-args xs fs))
              (result (base:apply fv args) argss))))]
  #:methods gen:monad
  [(define (chain f x)
     (state (λ (s)
              (match-define (result xv xs) (run x s))
              (match-define (result fv fs) (run (f xv) xs))
              (result fv fs))))])

(define (run m s) ((state-f m) s))

(define get
  (state (λ (s) (result s s))))

(define (set ns)
  (state (λ (s) (result s ns))))
;Definition bis hierher
  
(define fuga0
  (do [x <- get]
      (pure (printf "fuga0: ~a\n" x))
      (set "another state")
      (pure "result of fuga0")))

(define fuga1
  (do [x <- get]
      (pure (printf "fuga1: ~a\n" x))))

(define hoge
  (do [x <- fuga0]
      (pure (displayln x))
      fuga1
      [y <- get]
      (pure (printf "last: ~a\n" y))))

(run hoge "initial state")

Verwenden Sie für Konstanten die Reader-Monade.

Es ist ein ziemlicher Schmerz in Python, aber wenn Sie Ihr Bestes geben, sieht es so aus.

#Staatliche Monadendefinition von hier
from typing import Callable, TypeVar, Generic, Tuple


S = TypeVar("S") #Zustandstyp
R = TypeVar("R") #Rückgabetyp
A = TypeVar("A") #Neuer Rückgabetyp

class State(Generic[S, R]):
    def __init__(self, f: Callable[[S], Tuple[S, R]]):
        self._f = f
    
    def run(self, state: S) -> Tuple[S, R]:
        return self._f(state)
    
    @staticmethod
    def of(value: R):
        return State(lambda s: (value, s))
    
    def flatmap(self, g: Callable[[R], State[S, A]]) -> State[S, A]:
        def _new(state):
            f_ret, f_state = self.run(state)
            return g(f_ret).run(f_state)
        return State(_new)
    
    def map(self, g: Callable[[R], A]) -> State[S, A]:
        return self.flatmap(lambda x: State.of(g(x)))
    
    def then(self, m: State[S, A]) -> State[S, A]:
        return self.flatmap(lambda _: m)
    
    def value(self, v: A) -> State[S, A]:
        return self.map(lambda _: v)

get_m = State(lambda s: (s, s))

def set_m(new_state):
    return State(lambda s: (s, new_state))
#Bisherige Definition der staatlichen Monade

fuga0 = (get_m
    .map(lambda v: print(f"fuga0: {v}"))
    .then(set_m("another_state"))
    .value("result of fuga0"))

fuga1 = (get_m
    .map(lambda v: print(f"fuga1: {v}")))

hoge = (fuga0
    .map(print)
    .then(fuga1)
    .then(get_m)
    .map(lambda v: print(f"last: {v}")))

hoge.run("initial state")

Begrenzte Fortsetzung

Was ist begrenzte Fortsetzung? Warum können Sie mit Statusänderungen umgehen? Siehe Asai-senseis Tutorial.

(require racket/control)

(define (get)
  (shift k
         (λ (x)
           ((k x) x))))

(define (set s)
  (shift k
         (λ (x)
           ((k x) s))))

(define (run m s)
  ((reset
    (let ([ret (m)])
      (λ (_) ret))) s))


(define (fuga0)
  (printf "fuga0: ~a\n" (get))
  (set "another state")
  "result of fuga0")

(define (fuga1)
  (printf "fuga1: ~a\n" (get)))

(define (hoge)
  (displayln (fuga0))
  (fuga1)
  (printf "last: ~a\n" (get)))

(run hoge "initial state")

Zusammenfassung

Jeder sagt jeder anders.

Anstatt sich an das zu halten, was Sie als Programmierer wissen, erhöhen Sie die Anzahl der Werkzeuge und verwenden Sie sie ordnungsgemäß.

Außerdem enthält die Standard-Python-Bibliothek contextvars. Ich habe es diesmal nicht erwähnt, weil es anscheinend asynchron gemacht wurde.

Recommended Posts

Zusammenfassung, wie der Status mit mehreren Funktionen geteilt wird
Zusammenfassung der Verwendung von pandas.DataFrame.loc
Zusammenfassung der Verwendung von pyenv-virtualenv
Zusammenfassung der Verwendung von csvkit
[Python] Zusammenfassung der Verwendung von Split- und Join-Funktionen
[Python] Zusammenfassung der Funktionen eval / exec + Schreiben einer Zeichenfolge mit Zeilenumbrüchen
[Python] Zusammenfassung der Verwendung von Pandas
Wie man mit matplotlib mehrere Figuren betitelt
Ich habe versucht, das Entwicklungsstartverfahren von Django kurz zusammenzufassen
[Python2.7] Zusammenfassung der Verwendung von unittest
Zusammenfassung der Verwendung der Python-Liste
[Python2.7] Zusammenfassung der Verwendung des Unterprozesses
Zusammenfassung des Schreibens von AWS Lambda
Zusammenfassung zum Erstellen einer LAMP + Wordpress-Umgebung mit Sakura VPS
Zusammenfassung zum Importieren von Dateien in Python 3
[Python] Zeichnen mehrerer Diagramme mit Matplotlib
Zusammenfassung der Verwendung von MNIST mit Python
So legen Sie Attribute mit Mock of Python fest
So implementieren Sie "named_scope" von RubyOnRails mit Django
[Java] So wechseln Sie zwischen mehreren Java-Versionen
So geben Sie mit der Indexmethode mehrere Indizes zurück
Zusammenfassung zum Lesen numerischer Daten mit Python [CSV, NetCDF, Fortran Binary]
[Blender] Zusammenfassung der Installation / Aktualisierung / Deinstallation von Add-Ons
Freigeben von Ordnern für Docker und Windows mit Tensorflow
So zeigen Sie mehrere Bilder einer Galaxie in Kacheln an
So geben Sie die CSV eines mehrzeiligen Headers mit Pandas aus
Ableiten der MAP-Schätzung von HMM mit PyStruct
[Python] Zusammenfassung, wie die Farbe der Figur angegeben wird
Ableiten der MAP-Schätzung von HMM mit OpenGM
Wie man strukturiertes SVM von ChainCRF mit PyStruct lernt
[IPython] Freigeben eines IPython-Notizbuchs
Wie aktualisiere ich mit SQLAlchemy?
Wie man mit Theano besetzt
So trennen Sie Zeichenfolgen mit ','
Wie man RDP auf Fedora31 macht
Wie lösche ich mit SQLAlchemy?
[Python] Zusammenfassung zum Abrufen von Listen und Wörterbuchelementen
So aktivieren Sie das Lesen / Schreiben von net.Conn mit golang, um mit dem Kontext abzubrechen
[Linux] [C / C ++] Zusammenfassung, wie man pid, ppid, tid bekommt
So zeigen Sie eine Liste der mit pyenv installierbaren Versionen an
Vergleich der Verwendung von Funktionen höherer Ordnung in Python 2 und 3
Zusammenfassung zum Schreiben von in gRPC verwendeten .proto-Dateien
So brechen Sie RT mit tweepy ab
So extrahieren Sie Funktionen von Zeitreihendaten mit PySpark Basics
Python: So verwenden Sie Async mit
Umgang mit "Sie haben mehrere Authentifizierungs-Backends konfiguriert ..." (Django)
Stellen Sie mit SQL Alchemy eine Verbindung zu mehreren Datenbanken her
So erhalten Sie die ID von Type2Tag NXP NTAG213 mit nfcpy
So verwenden Sie virtualenv mit PowerShell
So installieren Sie Python-Pip mit Ubuntu20.04LTS
Umgang mit unausgeglichenen Daten
Grundlegende Grammatik des Python3-Systems (Verwendung von Funktionen, Schließung, Lambda-Funktion)
Erste Schritte mit Python
Herstellen einer Verbindung zum Cloud Firestore über Google Cloud-Funktionen mit Python-Code
Umgang mit dem DistributionNotFound-Fehler
Wie fange ich mit Django an?
10 Funktionen von "Sprache mit Batterie" Python
So überwachen Sie den Ausführungsstatus von sqlldr mit dem Befehl pv