Zurück, Zurück, [Hier](http: // yloiseau) Ein Hinweis zur Interpretation des Artikels in .net / articles / DesignPatterns / flyweight /).
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')
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