Python 将staticmethod与flyweight装饰器一起使用时出错
我有一个制作精灵飞锤的课程,我用一个装饰师来命名这个课程。下面是一些代码:Python 将staticmethod与flyweight装饰器一起使用时出错,python,python-3.x,decorator,python-decorators,flyweight-pattern,Python,Python 3.x,Decorator,Python Decorators,Flyweight Pattern,我有一个制作精灵飞锤的课程,我用一个装饰师来命名这个课程。下面是一些代码: class flyweight: def __init__(self, cls): self._cls = cls self.__instances = dict() def __call__(self, title): return self.__instances.setdefault((title), self._cls(title)) 在这个问题
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实现还是有办法解决这个问题?一旦装饰完成,包装对象的名称会自动指向装饰器返回的结果。在本例中,
Sprite
现在存储flyweight
的一个实例,该实例又包含一个属性,该属性存储原始包装类Sprite
的一个实例。例如,在声明后打印Sprite
,得到:
。但是,可以从\u cls
调用来自\u color的静态方法:
red = Sprite._cls.from_colour((125,0,0))
一个flyweight
装饰器确实应该将所有构造函数传递给底层类,包括@classmethod
和@staticmethod
替代构造函数。事实上,更一般地说,类装饰器确实应该保留包装的类的整个公共接口
而且,虽然我们可以很容易地修改flyweight
以专门通过Sprite
接口的其余部分,在本例中,这只是来自于_color
方法的,但对于一个不那么琐碎的类,或者对于一个不断变化的类来说,这将是一个痛苦的过程。实际上,制作一个只适用于单个类的装饰器有什么意义
那么,让我们将其更改为:
- 接受任何构造函数签名。理想情况下,我们希望在签名的哪个部分作为密钥进行配置,1但是为了避免事情变得太复杂,让我们将其作为第一个参数进行修复
- 传递类的整个公共接口,而不仅仅是它的
\uuu调用\uu
接口
因此:
一,。我使用过的其他一些库对此函数memo缓存有很好的设计。可能是cachetools
。对于类构造缓存来说,它应该同样有意义。虽然这是可行的,但我认为这不是一个很好的答案。显然,from_color
应该是Sprite
公共界面的一部分。但是,您现在必须通过私有属性调用它。更糟糕的是,Sprite
的用户不必知道的类的私有属性。特别是因为你应该能够在不改变任何东西的情况下将@flyweight
放入并取出,除了性能,而且如果它模糊了装饰类的界面,你肯定不能。完美。谢谢
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)