Updated flyweight with metaclass, made it more generic
diff --git a/flyweight.py b/flyweight.py
index 40c910fd..557f1272 100644
--- a/flyweight.py
+++ b/flyweight.py
@@ -6,6 +6,43 @@
 import weakref
 
 
+class FlyweightMeta(type):
+    def __new__(mcs, name, parents, dct):
+        """
+
+        :param name: class name
+        :param parents: class parents
+        :param dct: dict: includes class attributes, class methods,
+        static methods, etc
+        :return: new class
+        """
+
+        # set up instances pool
+        dct['pool'] = weakref.WeakValueDictionary()
+        return super(FlyweightMeta, mcs).__new__(mcs, name, parents, dct)
+
+    @staticmethod
+    def _serialize_params(cls, *args, **kwargs):
+        """Serialize input parameters to a key.
+        Simple implementation is just to serialize it as a string
+
+        """
+        args_list = map(str, args)
+        args_list.extend([str(kwargs), cls.__name__])
+        key = ''.join(args_list)
+        return key
+
+    def __call__(cls, *args, **kwargs):
+        key = FlyweightMeta._serialize_params(cls, *args, **kwargs)
+        pool = getattr(cls, 'pool', {})
+
+        instance = pool.get(key)
+        if not instance:
+            instance = super(FlyweightMeta, cls).__call__(*args, **kwargs)
+            pool[key] = instance
+        return instance
+
+
 class Card(object):
 
     """The object pool. Has builtin reference counting"""
@@ -27,6 +64,15 @@ def __new__(cls, value, suit):
     def __repr__(self):
         return "<Card: %s%s>" % (self.value, self.suit)
 
+
+class Card2(object):
+    __metaclass__ = FlyweightMeta
+
+    def __init__(self, *args, **kwargs):
+        # print('Init {}: {}'.format(self.__class__, (args, kwargs)))
+        pass
+
+
 if __name__ == '__main__':
     # comment __new__ and uncomment __init__ to see the difference
     c1 = Card('9', 'h')
@@ -42,6 +88,25 @@ def __repr__(self):
     c3 = Card('9', 'h')
     print(hasattr(c3, 'temp'))
 
+    # Tests with metaclass
+    instances_pool = getattr(Card2, 'pool')
+    cm1 = Card2('10', 'h', a=1)
+    cm2 = Card2('10', 'h', a=1)
+    cm3 = Card2('10', 'h', a=2)
+
+    assert (cm1 == cm2) != cm3
+    assert (cm1 is cm2) is not cm3
+    assert len(instances_pool) == 2
+
+    del cm1
+    assert len(instances_pool) == 2
+
+    del cm2
+    assert len(instances_pool) == 1
+
+    del cm3
+    assert len(instances_pool) == 0
+
 ### OUTPUT ###
 # (<Card: 9h>, <Card: 9h>)
 # (True, True)

I guess current implementation is not clean enough.
Updated implementation will work for python2, for python3 minor updates are required
