Ändere das Fliegengewichtsmuster in Pythonic (?) (2)

Wie bei Letztes Mal ein Memo bei der Interpretation des Artikels hier.

Mixin (Klassenmethode) mit Vererbung

Im Originaltext heißt es Mixin, aber ehrlich gesagt kommt es mir nicht. Sollten wir es als eine reine Vererbungsklasse betrachten, die eine bestimmte Funktion (Methode) bereitstellt und diese nicht alleine verwendet (= nicht instanziiert)?

Der Code selbst ist fast der gleiche wie [Verallgemeinerung der Factory mit Argumenten variabler Länge](http://qiita.com/FGtatsuro/items/9e45ee7a0e4165004dc0#Generalisierung der Factory mit Argumenten variabler Länge). Die Unterschiede sind wie folgt.

--Die von FlyweightFactory bereitgestellten Funktionen werden von der Klasse "Hoge" / "Piyo" durch Vererbung verwendet. --Verwenden Sie Klassen sowie Argumente variabler Länge als Wörterbuchschlüssel

python


class FlyweightMixin(object):

    _instances = {}

    @classmethod    
    def get_instance(cls, *args, **kwargs):
		# _Instanz ist eine Klassenvariable und wird von allen Klassen wiederverwendet, die von dieser Klasse erben.
        #Streit(*args, **kwargs)Eine Klasse, die als Wörterbuchschlüssel geerbt wurde, um zwischen Instanzen mit derselben, aber unterschiedlichen Klasse zu unterscheiden(cls)Muss auch verwendet werden.
        return cls._instances.setdefault((cls, args, tuple(kwargs.items())), cls(*args, **kwargs))

class Hoge(FlyweightMixin):
    def __init__(self, args1, kwargs1='test1'):
        self.args1 = args1
        self.kwargs1 = kwargs1

class Piyo(FlyweightMixin):
    def __init__(self, args1, kwargs1):
        self.args1 = args1
        self.kwargs1 = kwargs1


assert Hoge.get_instance(1, kwargs1=2) is Hoge.get_instance(1, kwargs1=2)
assert Hoge.get_instance(1, kwargs1=2) is not Hoge.get_instance(1, kwargs1=3)
assert Piyo.get_instance('a', kwargs1='b') is Piyo.get_instance('a', kwargs1='b')
assert Piyo.get_instance('a', kwargs1='b') is not Piyo.get_instance('a', kwargs1='c')

#Fälle mit denselben Argumenten, aber unterschiedlichen Klassen
#Klasse als Schlüssel des Wörterbuchs geerbt(cls)Wenn Sie nicht verwenden, schlägt diese Behauptung fehl.
assert Hoge.get_instance('a', kwargs1='b') is not Piyo.get_instance('a', kwargs1='b')

Mischen mit Vererbung (__new__ Methode)

Im vorherigen Beispiel "Die FlyweightMixin-Klasse ist nur Vererbung". Wenn Sie sie jedoch erstellen möchten, können Sie mithilfe von FlyweightMixin () eine Instanz der FlyweightMixin-Klasse erstellen. Im folgenden Beispiel wird der Prozess an die Methode "new" übertragen, die beim Erstellen einer Instanz immer aufgerufen wird, und in der Methode "init" wird eine Ausnahme ausgelöst, die nach der Methode "__new __" aufgerufen wird. Das Aufrufen von "FlyweightMixin ()" löst eine Ausnahme aus. Um die "FlyweightMixin" -Klasse zu verwenden, müssen Sie die "__init __" -Methode in der Unterklasse immer erben und überschreiben.

python


class FlyweightMixin(object):

    _instances = {}

    def __init__(self, *args, **kwargs):
        raise NotImplementedError

    def __new__(cls, *args, **kwargs):
        # Python2,Funktioniert mit Python 3
        instance = super(type(cls), cls).__new__(cls)
        #Nur Python 3 funktioniert:Python2 unterstützt das Aufrufen von Superfunktionen mit ausgelassenen Argumenten nicht
        # instance = super().__new__(cls)
        #Nur Python2 funktioniert:Python3 ist ein Objekt.__new__Argumente mit variabler Länge können nicht akzeptiert werden(Ich weiß nicht warum)
        # instance = super(type(cls), cls).__new__(cls, *args, **kwargs)
        return cls._instances.setdefault((cls, args, tuple(kwargs.items())), instance)

class Hoge(FlyweightMixin):
    def __init__(self, args1, kwargs1='test1'):
        self.args1 = args1
        self.kwargs1 = kwargs1

class Piyo(FlyweightMixin):
    def __init__(self, args1, kwargs1):
        self.args1 = args1
        self.kwargs1 = kwargs1

assert Hoge(1, kwargs1=2) is Hoge(1, kwargs1=2)
assert Hoge(1, kwargs1=2) is not Hoge(1, kwargs1=3)
assert Piyo('a', kwargs1='b') is Piyo('a', kwargs1='b')
assert Piyo('a', kwargs1='b') is not Piyo('a', kwargs1='c')
assert Hoge('a', kwargs1='b') is not Piyo('a', kwargs1='b')

(Ergänzung) Rückgabewert der Methode new`

Normalerweise gibt die Methode "new" eine neue Instanz der im ersten Argument angegebenen Klasse zurück. Andererseits speichert die Methode "new" von "FlyweightMixin" die erstellte Instanz im Wörterbuch "_instances" und gibt die gespeicherte Instanz ab dem zweiten Mal zurück.

Mit Dekorateur mischen

Im folgenden Beispiel wird in der Methode, die die Vererbung verwendet, die Logik des Flyweight-Musters, das der übergeordneten Klasse (FlyweightMixin) gegeben wurde, der Seite der untergeordneten Klasse unter Verwendung des Dekorators gegeben. Die Funktion flyweight ersetzt die Variable _instances (Wörterbuch) und die Methode __new__ (Funktionsobjekt, das die Logik des Flyweight-Musters definiert) für das als Argument verwendete Klassenobjekt und gibt es zurück.

python


#Wenn Sie es mit der classmethod-Funktion nicht zu einer Klassenmethode machen, tritt in Python2 ein Fehler auf.
# (ref.) 
# http://chikatoike.hatenadiary.jp/entry/2013/07/31/125624
# http://momijiame.tumblr.com/post/67251294770/pythone
# https://docs.python.org/3/whatsnew/3.0.html#operators-and-special-methods
# (2015/02/27 Nachtrag)
#Die statische Methodenfunktion war ebenfalls in Ordnung. Das Dokument betrachten__new__Die statische Methode eignet sich besser zum Einfügen?
# (ref.) https://docs.python.org/3.3/reference/datamodel.html#object.__new__
@classmethod
def _get_instance(cls, *args, **kwargs):
    instance = super(type(cls), cls).__new__(cls)
    #Jede Klasse ist ein Wörterbuch(cls._instances)Beseitigt die Notwendigkeit, Klassenobjekte in Schlüssel aufzunehmen
    return cls._instances.setdefault((args, tuple(kwargs.items())), instance)


def flyweight(cls):
    #Das dem Attribut des Klassenobjekts zugewiesene Funktionsobjekt ist
    # Python2: unbound method(=Muss die Instanz angeben, die beim Aufruf gebunden werden soll)
    # __new__Wird beim Instanziieren implizit aufgerufen
    #Was übergeben wird, ist ein Klassenobjekt(cls)Und eine Instanz dieser Klasse(self)ist nicht
    # Python3:Bleiben Sie als Funktionsobjekt
    cls._instances = {}
    print(_get_instance)
    cls.__new__ = _get_instance
    print(cls.__new__)
    return cls

# Hoge = flyweight(Hoge)Gleichwertig
@flyweight
class Hoge(object):
    def __init__(self, args1, kwargs1='test1'):
        self.args1 = args1
        self.kwargs1 = kwargs1

# Piyo = flyweight(Piyo)Gleichwertig
@flyweight
class Piyo(object):
    def __init__(self, args1, kwargs1):
        self.args1 = args1
        self.kwargs1 = kwargs1

assert Hoge(1, kwargs1=2) is Hoge(1, kwargs1=2)
assert Hoge(1, kwargs1=2) is not Hoge(1, kwargs1=3)
assert Piyo('a', kwargs1='b') is Piyo('a', kwargs1='b')
assert Piyo('a', kwargs1='b') is not Piyo('a', kwargs1='c')
assert Hoge('a', kwargs1='b') is not Piyo('a', kwargs1='b')

Recommended Posts

Ändere das Fliegengewichtsmuster in Pythonic (?) (3)
Ändere das Fliegengewichtsmuster in Pythonic (?) (2)
Ändere das Fliegengewichtsmuster in Pythonic (?) (1)
[Python] Ändere das Alphabet in eine Zahl
Lernen Sie das Designmuster "Flyweight" in Python
Skript zum Ändern der Beschreibung von Fasta
[Python] So ändern Sie das Datumsformat (Anzeigeformat)
Ändern Sie den Dezimalpunkt der Protokollierung von, nach.
Fliegengewichtsmuster in Java
Der Weg nach Pythonista
Über das Besuchermuster
Der Weg nach Djangoist
[Python] Ändern Sie die Cache-Steuerung von Objekten, die in den Cloud-Speicher hochgeladen wurden
Ändern Sie das Standardausgabeziel in eine Datei in Python
Eine Einführung in die Objektorientierung: Ändern Sie den internen Status eines Objekts
Ich möchte mit Numpy die japanische Flagge in die Palau-Flagge ändern
Ändern Sie die Lautstärke von Pepper entsprechend der Umgebung (Ton).
Ändern Sie die Meldung, die beim Anmelden bei Raspberry Pi angezeigt wird
Ändern Sie das Installationsziel, wenn --user zu pip hinzugefügt wird
So ändern Sie das Layout von Jupyter
Punkt entsprechend dem Bild
Der Weg zum Herunterladen von Matplotlib
Ändern Sie das Thema von Jupyter
Ändern Sie den Stil von matplotlib
So ändern Sie die Python-Version
Wie benutzt man den Dekorateur?
So erhöhen Sie die Achse
So starten Sie die erste Projektion
So ändern Sie die Protokollstufe von Azure SDK für Python
So ändern Sie die Farbe nur der mit Tkinter gedrückten Taste
Ändern Sie die Y-Achsenskala von Matplotlib in die Exponentialschreibweise (10-te Potenzschreibweise).
Fühlen Sie sich frei, das Legendenlabel mit Seaborn in Python zu ändern
[Los] Erstellen Sie einen CLI-Befehl, um die Erweiterung des Bildes zu ändern
Ändern Sie die Bash-Eingabeaufforderung zur einfachen Anzeige in eine einfache Farbe
Ich habe zusammengefasst, wie die Boot-Parameter von GRUB und GRUB2 geändert werden
Ändern Sie die aktive Version in Pyenv von Anaconda in einfaches Python