问题
I am trying to create a class that doesn't re-create an object with the same input parameters. When I try to instantiate a class with the same parameters that were used to create an already-existing object, I just want my new class to return a pointer to the already-created (expensively-created) object. This is what I have tried so far:
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'
This is my first venture into overriding __new__
and I'm convinced I'm not going about it the right way. Set me straight, please.
回答1:
First, use Upper Case Class Names in Python.
Second, use a Factory design pattern to solve this problem.
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]
This is much simpler than fooling around with new and having class level pools of objects.
回答2:
Here's a class decorator to make a class a multiton:
def multiton(cls):
instances = {}
def getinstance(id):
if id not in instances:
instances[id] = cls(id)
return instances[id]
return getinstance
(This is a slight variant of the singleton decorator from PEP 318.)
Then, to make your class a multiton, use the decorator:
@multiton
class MyObject( object ):
def __init__( self, arg):
self.id = arg
# other expensive stuff
Now, if you instantiate MyObject with the same id, you get the same instance:
a = MyObject(1)
b = MyObject(2)
c = MyObject(2)
a is b # False
b is c # True
来源:https://stackoverflow.com/questions/669932/how-to-create-a-class-that-doesnt-re-create-an-object-with-identical-input-para