Python factory pattern implementation with metaclass -


i have issues trying implement easy use abstract factory.

goal

to able define concrete factories way :

class myconcretefactory( ... ):     @classmethod     def __load(cls, key):         obj = ... # loading instructions here         return obj 

to able use concretre factories way

obj = myconcretefactory[key] 

my attempt

i tried define metaclass factories wich override bracket operator , encapsulate factory pattern :

class __factorymeta(type):      __ressources = {}      @classmethod     def __getitem__(cls, key):         if key not in cls.__ressources:             cls.__ressources[key] = cls.__load(key)         return cls.__ressources[key]      @classmethod     def __load(cls, key):         raise notimplementederror   class concretefactory(metaclass=__factorymeta):      @classmethod     def __load(cls, key):         return "toto"   = concretefactory["mykey"] print(a) 

issue

this failed because __load method called 1 metaclass , not 1 concrete class. result :

traceback (most recent call last):   file "c:\users\walter\workspace\game\src\core\factories.py", line 34, in <module>     = concretefactory["mykey"]   file "c:\users\walter\workspace\game\src\core\factories.py", line 19, in __getitem__     cls.__ressources[key] = cls.__load(key)   file "c:\users\walter\workspace\game\src\core\factories.py", line 24, in __load     raise notimplementederror notimplementederror 

i tried remove __load method meta class got (predictable) error :

traceback (most recent call last):   file "c:\users\walter\workspace\game\src\core\factories.py", line 30, in <module>     = concretefactory["mykey"]   file "c:\users\walter\workspace\game\src\core\factories.py", line 19, in __getitem__     cls.__ressources[key] = cls.__load(key) attributeerror: type object '__factorymeta' has no attribute '_factorymeta__load' 

questions

is there way access class method metaclass ? wrong , should in other way ? wich way ?

solution

class __factorymeta(type):      ressources = {}      def __getitem__(cls, key):         if key not in cls.ressources:             cls.ressources[key] = cls.load(key)         return cls.ressources[key]      def load(cls, key):         raise notimplementederror   class concretefactory(metaclass=__factorymeta):      @classmethod     def load(cls, key):         return "toto"   = concretefactory["mykey"] print(a) 

you should not use @classmethod in metaclass. instance of metaclass class so:

def __getitem__(cls, key): 

is class and:

@classmethod def __getitem__(metacls, key): 

gets metaclass first argument.

eiher case, believe metaclasses make problem more complicated. believe more viable approach create base factory class, subclass accordingly, , use subclass'es instance factory.


Comments

Popular posts from this blog

java - nested exception is org.hibernate.exception.SQLGrammarException: could not extract ResultSet Hibernate+SpringMVC -

sql - Postgresql tables exists, but getting "relation does not exist" when querying -

asp.net mvc - breakpoint on javascript in CSHTML? -