I have a class for making sprites flyweight and I am using a decorator to call this class. Here is some code:
class flyweight:
def __init__(self, cls):
self._cls = cls
self.__instances = dict()
def __call__(self, title):
return self.__instances.setdefault((title), self._cls(title))
In this question I'll just simplify the code to show what is relevant.
@flyweight
class Sprite:
def __init__(self, title, surf=None):
self.title = title
self.surf = surf if surf is not None else pygame.image.load('Images/Sprites/'+title+'.png').convert_alpha()
self.w, self.h = self.surf.get_size()
@staticmethod
def from_colour(colour, size=(40,40)):
surf = pygame.Surface(size).convert(); surf.fill(colour)
return Sprite(colour, surf)
red = Sprite.from_colour((125,0,0))
But this gives me the error:
AttributeError: 'flyweight' object has no attribute 'from_colour'
Should I remodel my flyweight implementation or is there some way around this?
A
flyweightdecorator really ought to pass through all constructors to the underlying class, including@classmethodand@staticmethodalternate constructors. In fact, more generally, a class decorator really ought to preserve the wrapped class's entire public interface.And, while we could easily modify
flyweightto specifically pass through the rest of theSpriteinterface, which in this case is just thatfrom_colourmethod, that would be a pain for a less trivial class, or for a class that ever changes. And really, what's the point of making a decorator that only works with a single class?So, let's change it to:
Take any constructor signature. Ideally we'd want to make it configurable on what part of the signature counts as the key,1 but to keep things from getting too complicated, let's just fix it as the first argument.
Pass through the entire public interface of the class, not just its
__call__interface.So:
1. Some other library I've used has a nice design for this for function memo caches. Probably
cachetools. And it ought to make just as much sense for class construction caches.