我有一个使精灵轻量化的类,并且我正在使用装饰器来调用此类。这是一些代码:
class flyweight:
def __init__(self, cls):
self._cls = cls
self.__instances = dict()
def __call__(self, title):
return self.__instances.setdefault((title), self._cls(title))
在这个问题中,我将简化代码以显示相关内容。
@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))
但这给了我错误:
AttributeError: 'flyweight' object has no attribute 'from_colour'
我应该重塑我的flyweight实现,还是可以解决这个问题?
答案 0 :(得分:1)
装饰后,包装对象的名称会自动指向装饰器的返回结果。在这种情况下,Sprite
现在存储flyweight
的实例,而该实例依次包含一个属性,该属性存储原始包装类Sprite
的实例。例如,在声明后打印Sprite
会得到:<__main__.flyweight object at 0x102373080>
。但是,可以从staticmethod
调用from_colour
_cls
:
red = Sprite._cls.from_colour((125,0,0))
答案 1 :(得分:0)
flyweight
装饰器确实应该通过所有构造函数传递给基础类,包括@classmethod
和@staticmethod
备用构造函数。实际上,更一般地说,类装饰器确实应该保留包装的类的整个公共接口。
并且,尽管我们可以轻松地修改flyweight
以专门通过Sprite
接口的其余部分,在这种情况下,该接口只是from_colour
方法,但这对于一个不太琐碎的课程,或一个不断变化的课程。真的,制作仅适用于单个类的装饰器有什么意义?
因此,我们将其更改为:
获取任何构造函数签名。理想情况下,我们希望使它可以在签名的哪一部分算作密钥 1 上进行配置,但是为了避免事情变得过于复杂,我们将其固定为第一个参数。
通过类的整个公共接口,而不仅仅是其__call__
接口。
所以:
class flyweight:
def __init__(self, cls):
self._cls = cls
self.__instances = dict()
def __call__(self, key, *args, **kw):
return self.__instances.setdefault(key, self._cls(key, *args, **kw))
def __getattr__(self, name):
if not name.startswith('_'):
return getattr(self._cls, name)
1。我使用过的其他一些库为此功能备忘缓存设计得很好。可能是cachetools
。对于类构造缓存,它应该同样有意义。