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