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

Zurück, Zurück, [Hier](http: // yloiseau) Ein Hinweis zur Interpretation des Artikels in .net / articles / DesignPatterns / flyweight /).

Fliegengewichtsmuster mit Metaklasse (Unterklasse der Typklasse)

Vor der Methode, die die Meta-Klasse verwendet, werde ich auf die vorausgesetzte type-Klasse eingehen. Die Typklasse wird beim Erstellen einer Klassendefinition (= Klassenobjekt) verwendet.

python


def methodA(self):
    print('methodA')

#Klassenname, übergeordnete Klasse(Mehrere Spezifikationen sind möglich), Namensraum(Hier ausgedrückt durch ein Wörterbuch'methodA'Die Funktion methodA ist mit verknüpft)Nimmt als Argument
#Erstellen Sie ein Klassenobjekt
ClassA = type('ClassA', (object,), {'methodA': methodA})
a = ClassA()
a.methodA()

#Entspricht der folgenden Definition
# class ClassA(object):
#     def methodA(self):
#        print('methodA')

Wie oben erwähnt, ist "Typ" eine Klasse. Daher können Unterklassen erstellt werden. Unterklassen können verwendet werden, um Klassenobjekte anstelle der Klasse "type" zu erstellen, und Sie können beim Erstellen von Klassenobjekten eine Verarbeitung hinzufügen, indem Sie die Methoden "new" und "init" überschreiben.

python


def methodA(self):
    print('methodA')

class Meta(type):
    def __new__(cls, name, bases, namespace):
        #Sie können beim Erstellen eines Klassenobjekts zusätzliche Verarbeitung einfügen
        print('hoge')
        return super().__new__(cls, name, bases, namespace)

#Metaklasse statt Typklasse(=Eine Unterklasse der Typklasse)Kann verwendet werden
ClassA = Meta('ClassA', (object,), {'methodA': methodA})
a = ClassA()
a.methodA()

Wenn Sie beim Erstellen eines Klassenobjekts in normaler Klassendefinitionssyntax etwas anderes als die Typklasse verwenden möchten, verwenden Sie das Schlüsselwort metaclass in Python3. Die zu diesem Zeitpunkt angegebene Klasse wird als Metaklasse bezeichnet.

python


class Meta(type):
    def __new__(cls, name, bases, namespace):
        #Sie können beim Erstellen eines Klassenobjekts zusätzliche Verarbeitung einfügen
        print('hoge')
        return super().__new__(cls, name, bases, namespace)

class ClassA(object, metaclass=Meta):
#Angeben der Python2-Metaklasse
#class ClassA(object):
#    __metaclass__ =Meta
    def methodA(self):
        print('methodA')

a = ClassA()
a.methodA()

Das folgende Beispiel zeigt das Einfügen der Flyweight-Musterlogik beim Erstellen eines Klassenprojekts unter Verwendung der Eigenschaft der Metaklasse, dass "Verarbeitung beim Erstellen eines Klassenobjekts hinzugefügt werden kann".

python


class MetaFlyweight(type):
    def __new__(cls, name, bases, namespace):
        #Typklasse__new__Methode gibt Klassenobjekt zurück
        clsobj = type.__new__(cls, name, bases, namespace)

        clsobj._instances = {}
        def _get_instance(cls, *args, **kargs):
            instance = super(cls, cls).__new__(cls)
            return cls._instances.setdefault(
                    (args, tuple(kargs.items())), instance)
        #Es funktioniert, ohne es zu einer statischen Methode zu machen, aber machen Sie es zu einer statischen Methode gemäß der folgenden Beschreibung
        # (ref.) https://docs.python.org/3.3/reference/datamodel.html#object.__new__
        clsobj.__new__ = staticmethod(_get_instance)
        return clsobj

class Hoge(object, metaclass=MetaFlyweight):
#Angeben der Python2-Metaklasse
#class Hoge(object):
#    __metaclass__ = MetaFlyweight
    def __init__(self, args1, kwargs1='test1'):
        self.args1 = args1
        self.kwargs1 = kwargs1

class Piyo(object, metaclass=MetaFlyweight):
#Angeben der Python2-Metaklasse
#class Piyo(object):
#    __metaclass__ = MetaFlyweight
    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')
assert Hoge('a', kwargs1='b') is not Piyo('a', kwargs1='b')

Fliegengewichtsmuster (Funktion) mit Metaklasse

Es ist jedoch nicht immer erforderlich, eine Unterklasse der Klasse "type" zu generieren. Wenn ein Klassenobjekt erstellt wird, wird die Typklasse aufgerufen, die den "Klassennamen (Zeichenfolge)", die "übergeordnete Klasse (Taple)" und den "Namespace (Wörterbuch)" enthält. Was hier jedoch benötigt wird, ist keine "Typ" -Klasse (oder Unterklasse), sondern ein "aufrufbares Objekt, das die obigen drei Argumente empfängt". Daher ist es auch möglich, die Funktion in der Metaklasse wie folgt anzugeben.

python


def meta_flyweight(name, bases, namespace):
    clsobj = type(name, bases, namespace)

    clsobj._instances = {}
    def _get_instance(cls, *args, **kargs):
        instance = super(cls, cls).__new__(cls)
        return cls._instances.setdefault(
                (args, tuple(kargs.items())), instance)
    #Es funktioniert, ohne es zu einer statischen Methode zu machen, aber machen Sie es zu einer statischen Methode gemäß der folgenden Beschreibung
    # (ref.) https://docs.python.org/3.3/reference/datamodel.html#object.__new__
    clsobj.__new__ = staticmethod(_get_instance)
    return clsobj

class Hoge(object, metaclass=meta_flyweight):
#Angeben der Python2-Metaklasse
#class Hoge(object):
#    __metaclass__ = meta_flyweight
    def __init__(self, args1, kwargs1='test1'):
        self.args1 = args1
        self.kwargs1 = kwargs1

class Piyo(object, metaclass=meta_flyweight):
#Angeben der Python2-Metaklasse
#class Piyo(object):
#    __metaclass__ = meta_flyweight
    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')
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 Gebietsschema von Amazon Linux mithilfe der Lineinfile von Ansible in Japan
[Python] Ändern Sie den Namen der Bilddatei in eine Seriennummer
Ä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
Verwendung des Generators
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