class FlyweightMixin(object):

    _instances = dict()

    @classmethod
    def get_instance(cls, *args, **kargs):
        return cls._instances.setdefault(
                                (cls, args, tuple(kargs.items())), 
                                cls(*args, **kargs))


#----------------------------------------------------------
class Spam(FlyweightMixin):

    def __init__(self, a, b):
        self.a = a
        self.b = b


class Egg(FlyweightMixin):

    def __init__(self, x, y):
        self.x = x
        self.y = y


assert Spam.get_instance(1, 2) is Spam.get_instance(1, 2)
assert Egg.get_instance('a', 'b') is Egg.get_instance('a', 'b')
assert Spam.get_instance(1, 2) is not Egg.get_instance(1, 2)

# Subclassing a flyweight class
class SubSpam(Spam):
    pass

assert SubSpam.get_instance(1,2) is SubSpam.get_instance(1,2)
assert Spam.get_instance(1,2) is not SubSpam.get_instance(1,2)
