Wie bei Letztes Mal ein Memo bei der Interpretation des Artikels hier.
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')
__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')
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.
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