我试图创建一个不重新创建具有相同输入参数的对象的类.当我尝试使用与创建已存在对象相同的参数来实例化一个类时,我只希望我的新类返回一个指向已经创建的(昂贵创建的)对象的指针.这是我到目前为止所尝试的:
class myobject0(object): # At first, I didn't realize that even already-instantiated # objects had their __init__ called again instances = {} def __new__(cls,x): if x not in cls.instances.keys(): cls.instances[x] = object.__new__(cls,x) return cls.instances[x] def __init__(self,x): print 'doing something expensive' class myobject1(object): # I tried to override the existing object's __init__ # but it didnt work. instances = {} def __new__(cls,x): if x not in cls.instances.keys(): cls.instances[x] = object.__new__(cls,x) else: cls.instances[x].__init__ = lambda x: None return cls.instances[x] def __init__(self,x): print 'doing something expensive' class myobject2(object): # does what I want but is ugly instances = {} def __new__(cls,x): if x not in cls.instances.keys(): cls.instances[x] = object.__new__(cls,x) cls.instances[x]._is_new = 1 else: cls.instances[x]._is_new = 0 return cls.instances[x] def __init__(self,x): if self._is_new: print 'doing something expensive'
这是我第一次尝试压倒一切__new__
,我确信我不会以正确的方式解决这个问题.请让我直截了当.
这是一个类装饰器,使类成为多个:
def multiton(cls): instances = {} def getinstance(id): if id not in instances: instances[id] = cls(id) return instances[id] return getinstance
(这是来自PEP 318的单件装饰器的略微变体.)
然后,要使您的类成为多圈,请使用装饰器:
@multiton class MyObject( object ): def __init__( self, arg): self.id = arg # other expensive stuff
现在,如果使用相同的id实例化MyObject,则会获得相同的实例:
a = MyObject(1) b = MyObject(2) c = MyObject(2) a is b # False b is c # True
首先,在Python中使用大写字母类名称.
其次,使用Factory设计模式来解决这个问题.
class MyObject( object ): def __init__( self, args ): pass # Something Expensive class MyObjectFactory( object ): def __init__( self ): self.pool = {} def makeMyObject( self, args ): if args not in self.pool: self.pool[args] = MyObject( args ) return self.pool[args]
这比使用新的具有类级别对象池的方式简单得多.