Ein Memo, das den Artikel interpretiert, der von der Person neben mir unterrichtet wurde.
Eine Fabrik ist für ein Ziel definiert. Der folgende Code entspricht weitgehend dem Originalartikel, mit Änderungen an benannten Argumenten.
python
class Hoge(object):
def __init__(self, args1, kwargs1='test1'):
self.args1 = args1
self.kwargs1 = kwargs1
class HogeFactory(object):
def __init__(self):
self._instances = {}
def get_instance(self, args1, kwargs1):
if ((args1), (kwargs1)) not in self._instances:
self._instances[((args1), (kwargs1))] = Hoge(args1, kwargs1=kwargs1)
return self._instances[((args1), (kwargs1))]
class Piyo(object):
def __init__(self, args1, kwargs1, kwargs2):
self.args1 = args1
self.kwargs1 = kwargs1
self.kwargs2 = kwargs2
class PiyoFactory(object):
def __init__(self):
self._instances = {}
def get_instance(self, args1, kwargs1='test1', kwargs2='test2'):
if ((args1), (kwargs1, kwargs2)) not in self._instances:
self._instances[((args1), (kwargs1, kwargs2))] = Piyo(args1, kwargs1=kwargs1, kwargs2=kwargs2)
return self._instances[((args1), (kwargs1, kwargs2))]
hogeFactory = HogeFactory()
piyoFactory = PiyoFactory()
assert hogeFactory.get_instance(1, kwargs1=2) is hogeFactory.get_instance(1, kwargs1=2)
assert hogeFactory.get_instance(1, kwargs1=2) is not hogeFactory.get_instance(1, kwargs1=3)
assert piyoFactory.get_instance('a', kwargs1='b', kwargs2='c') is piyoFactory.get_instance('a', kwargs1='b', kwargs2='c')
assert piyoFactory.get_instance('a', kwargs1='b', kwargs2='c') is not piyoFactory.get_instance('a', kwargs1='b', kwargs2='d')
Der Grund, warum eine Factory für ein Ziel benötigt wurde, war, dass die Signatur des Konstruktors jedes Ziels unterschiedlich war = die Signatur der Methode "get_instance" war unterschiedlich. Sie können Pythons Argumente mit variabler Länge verwenden, um Unterschiede in den Signaturen zu absorbieren.
python
class FlyweightFactory(object):
def __init__(self, cls):
self._instances = {}
self._cls = cls
def get_instance(self, *args, **kwargs):
return self._instances.setdefault((args, tuple(kwargs.items())), self._cls(*args, **kwargs))
class Hoge(object):
def __init__(self, args1, kwargs1='test1'):
self.args1 = args1
self.kwargs1 = kwargs1
class Piyo(object):
def __init__(self, args1, kwargs1, kwargs2):
self.args1 = args1
self.kwargs1 = kwargs1
self.kwargs2 = kwargs2
hogeFactory = FlyweightFactory(Hoge)
piyoFactory = FlyweightFactory(Piyo)
assert hogeFactory.get_instance(1, kwargs1=2) is hogeFactory.get_instance(1, kwargs1=2)
assert hogeFactory.get_instance(1, kwargs1=2) is not hogeFactory.get_instance(1, kwargs1=3)
assert piyoFactory.get_instance('a', kwargs1='b', kwargs2='c') is piyoFactory.get_instance('a', kwargs1='b', kwargs2='c')
assert piyoFactory.get_instance('a', kwargs1='b', kwargs2='c') is not piyoFactory.get_instance('a', kwargs1='b', kwargs2='d')
Wenn Sie die oben genannte "Flyweight Factory" dekorieren, können Sie sie einfacher schreiben.
python
class Flyweight(object):
def __init__(self, cls):
self._instances = {}
self._cls = cls
def __call__(self, *args, **kwargs):
return self._instances.setdefault((args, tuple(kwargs.items())), self._cls(*args, **kwargs))
@Flyweight
class Hoge(object):
def __init__(self, args1, kwargs1='test1'):
self.args1 = args1
self.kwargs1 = kwargs1
@Flyweight
class Piyo(object):
def __init__(self, args1, kwargs1, kwargs2):
self.args1 = args1
self.kwargs1 = kwargs1
self.kwargs2 = kwargs2
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', kwargs2='c') is Piyo('a', kwargs1='b', kwargs2='c')
assert Piyo('a', kwargs1='b', kwargs2='c') is not Piyo('a', kwargs1='b', kwargs2='d')
Der Dekorateur wird aufgerufen, indem das angehängte Ziel als Argument verwendet wird. Der diesem Prozess entsprechende Code kann ohne Verwendung eines Dekorateurs wie folgt geschrieben werden. Anstatt "get_instance" aufzurufen, gibt es einen Unterschied beim Lesen der Flyweight-Instanz als Funktion, aber Sie können sehen, dass sie sich nicht so stark vom vorherigen Snippet unterscheidet.
(ref. http://docs.python.jp/3.4/reference/datamodel.html#object.call)
python
class Flyweight(object):
def __init__(self, cls):
self._instances = {}
self._cls = cls
def __call__(self, *args, **kwargs):
return self._instances.setdefault((args, tuple(kwargs.items())), self._cls(*args, **kwargs))
class Hoge(object):
def __init__(self, args1, kwargs1='test1'):
self.args1 = args1
self.kwargs1 = kwargs1
class Piyo(object):
def __init__(self, args1, kwargs1, kwargs2):
self.args1 = args1
self.kwargs1 = kwargs1
self.kwargs2 = kwargs2
# Hoge,Nehmen Sie Piyo als Argument,Erstellen Sie eine Flyweight-Instanz.
Hoge = Flyweight(Hoge)
Piyo = Flyweight(Piyo)
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', kwargs2='c') is Piyo('a', kwargs1='b', kwargs2='c')
assert Piyo('a', kwargs1='b', kwargs2='c') is not Piyo('a', kwargs1='b', kwargs2='d')
Darüber hinaus ist es nicht erforderlich, eine Klasse zu sein, solange sie aufrufbar ist. Dies ist die Implementierung mit dem folgenden Abschluss.
python
def flyweight(cls):
instances = {}
return lambda *args, **kwargs: instances.setdefault((args, tuple(kwargs.items())), cls(*args, **kwargs))
@flyweight
class Hoge(object):
def __init__(self, args1, kwargs1='test1'):
self.args1 = args1
self.kwargs1 = kwargs1
@flyweight
class Piyo(object):
def __init__(self, args1, kwargs1, kwargs2):
self.args1 = args1
self.kwargs1 = kwargs1
self.kwargs2 = kwargs2
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', kwargs2='c') is Piyo('a', kwargs1='b', kwargs2='c')
assert Piyo('a', kwargs1='b', kwargs2='c') is not Piyo('a', kwargs1='b', kwargs2='d')
Der entsprechende Code ohne Dekorateur sieht folgendermaßen aus:
python
def flyweight(cls):
instances = {}
return lambda *args, **kwargs: instances.setdefault((args, tuple(kwargs.items())), cls(*args, **kwargs))
class Hoge(object):
def __init__(self, args1, kwargs1='test1'):
self.args1 = args1
self.kwargs1 = kwargs1
class Piyo(object):
def __init__(self, args1, kwargs1, kwargs2):
self.args1 = args1
self.kwargs1 = kwargs1
self.kwargs2 = kwargs2
Hoge = flyweight(Hoge)
Piyo = flyweight(Piyo)
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', kwargs2='c') is Piyo('a', kwargs1='b', kwargs2='c')
assert Piyo('a', kwargs1='b', kwargs2='c') is not Piyo('a', kwargs1='b', kwargs2='d')
Diese Methode ist sehr intelligent, hat jedoch den Nachteil, dass Sie keine Unterklasse der Klasse "Hoge" / "Piyo" erstellen können. Dies liegt daran, dass das "Hoge" / "Piyo" keine Klasse mehr ist, sondern ein Funktionsobjekt, wie Sie im Code sehen können, der keine Dekoratoren verwendet. Daher führt der folgende Code zu einem Fehler.
python
def flyweight(cls):
instances = {}
return lambda *args, **kwargs: instances.setdefault((args, tuple(kwargs.items())), cls(*args, **kwargs))
@flyweight
class Hoge(object):
def __init__(self, args1, kwargs1='test1'):
self.args1 = args1
self.kwargs1 = kwargs1
@flyweight
class Piyo(object):
def __init__(self, args1, kwargs1, kwargs2):
self.args1 = args1
self.kwargs1 = kwargs1
self.kwargs2 = kwargs2
#Hoge ist keine Klasse mehr und kann nicht vererbt werden
class Hoge2(Hoge):
def __init__(self, args1, kwargs1='test1'):
super().__init__(args1, kwargs1=kwargs1)
In dem Sinne, dass "Hoge" / "Piyo" aufgrund des Dekorateurs keine Klasse mehr ist, ändert es sich nicht, selbst wenn der Dekorateur durch eine Klasse ausgedrückt wird, aber es gibt eine Instanz der "Flyweight" -Klasse, die die "Hoge" / "Piyo" -Klasse ersetzt. Es ist das Miso, das die ursprüngliche Klasse enthält. Daher kann es mit dem folgenden Code in Unterklassen unterteilt werden.
python
class Flyweight(object):
def __init__(self, cls):
self._instances = {}
self._cls = cls
def __call__(self, *args, **kwargs):
return self._instances.setdefault((args, tuple(kwargs.items())), self._cls(*args, **kwargs))
@Flyweight
class Hoge(object):
def __init__(self, args1, kwargs1='test1'):
self.args1 = args1
self.kwargs1 = kwargs1
@Flyweight
class Piyo(object):
def __init__(self, args1, kwargs1, kwargs2):
self.args1 = args1
self.kwargs1 = kwargs1
self.kwargs2 = kwargs2
# Hoge(Die Entität ist eine Flyweight-Instanz)Ist eine Instanzvariable, die die ursprüngliche Klasse enthält_Habe cls
class Hoge2(Hoge._cls):
def __init__(self, args1, kwargs1='test1'):
super().__init__(args1, kwargs1=kwargs1)
Recommended Posts