Comme pour Dernière fois, une note lors de l'interprétation de l'article ici.
Dans le texte original, cela s'appelle Mixin, mais honnêtement, cela ne me vient pas. Doit-elle être considérée comme une classe d'héritage uniquement qui fournit une certaine fonction (méthode) et n'est pas utilisée (= non instanciée) par elle-même?
Le code lui-même est presque le même que [Généralisation de l'usine en utilisant des arguments de longueur variable](http://qiita.com/FGtatsuro/items/9e45ee7a0e4165004dc0#Généralisation de l'usine en utilisant des arguments de longueur variable). Les différences sont les suivantes.
Hoge
/ Piyo
par héritage.
--Utilisez des classes ainsi que des arguments de longueur variable comme clés de dictionnairepython
class FlyweightMixin(object):
_instances = {}
@classmethod
def get_instance(cls, *args, **kwargs):
# _instance est une variable de classe et est réutilisée par toutes les classes qui héritent de cette classe.
#argument(*args, **kwargs)Une classe héritée en tant que clé de dictionnaire pour distinguer les instances avec les mêmes classes mais différentes(cls)Doit également être utilisé.
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')
#Cas avec les mêmes arguments mais des classes différentes
#Classe héritée comme clé du dictionnaire(cls)Si vous n'utilisez pas, cette assertion échouera.
assert Hoge.get_instance('a', kwargs1='b') is not Piyo.get_instance('a', kwargs1='b')
__new__
)Dans l'exemple précédent, "La classe FlyweightMixin
est l'héritage uniquement ", mais si vous souhaitez la créer, vous pouvez créer une instance de la classe FlyweightMixin en utilisant FlyweightMixin ()
.
Dans l'exemple suivant, le processus est transféré vers la méthode __new__
qui est toujours appelée lorsqu'une instance est créée, et une exception est levée dans la méthode __init__
qui est appelée après la méthode __new__
.
L'appel de FlyweightMixin ()
lève une exception, donc pour utiliser la classe FlyweightMixin
, vous devez toujours hériter et remplacer la méthode __init __
dans la sous-classe.
python
class FlyweightMixin(object):
_instances = {}
def __init__(self, *args, **kwargs):
raise NotImplementedError
def __new__(cls, *args, **kwargs):
# Python2,Fonctionne avec Python 3
instance = super(type(cls), cls).__new__(cls)
#Seul Python 3 fonctionne:Python2 ne prend pas en charge l'appel de super fonctions avec des arguments omis
# instance = super().__new__(cls)
#Seul Python2 fonctionne:Python3 est un objet.__new__Impossible d'accepter les arguments de longueur variable(Je ne sais pas pourquoi)
# 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')
__new__
Normalement, la méthode __new__
renvoie une nouvelle instance de la classe donnée dans le premier argument. D'autre part, la méthode __new__
de FlyweightMixin
enregistre l'instance créée dans le dictionnaire _instances
et renvoie l'instance enregistrée à partir de la deuxième fois.
Dans l'exemple suivant, la logique de modèle Flyweight qui a été donnée à la classe parente (FlyweightMixin
) dans la méthode utilisant l'héritage est donnée au côté de la classe enfant à l'aide d'un décorateur. La fonction flyweight
remplace la variable _instances
(dictionnaire) et la méthode __new__
(objet fonction qui définit la logique du modèle Flyweight) pour l'objet de classe pris comme argument et le renvoie.
python
#Si vous n'en faites pas une méthode de classe avec la fonction classmethod, une erreur se produira dans Python2.
# (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 Addendum)
#La fonction staticmethod était bien aussi. Consulter le document__new__La méthode statique est plus appropriée pour mettre en?
# (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)
#Chaque classe est un dictionnaire(cls._instances)Élimine le besoin d'inclure des objets de classe dans les clés
return cls._instances.setdefault((args, tuple(kwargs.items())), instance)
def flyweight(cls):
#L'objet fonction affecté à l'attribut de l'objet classe est
# Python2: unbound method(=Doit spécifier l'instance à lier à l'appel)
# __new__Est implicitement appelée lors de l'instanciation
#Ce qui est passé est un objet de classe(cls)Et une instance de cette classe(self)n'est pas
# Python3:Rester en tant qu'objet de fonction
cls._instances = {}
print(_get_instance)
cls.__new__ = _get_instance
print(cls.__new__)
return cls
# Hoge = flyweight(Hoge)Équivalent à
@flyweight
class Hoge(object):
def __init__(self, args1, kwargs1='test1'):
self.args1 = args1
self.kwargs1 = kwargs1
# Piyo = flyweight(Piyo)Équivalent à
@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