Come creare una classe che non ri-creare un oggetto con parametri di input identici

StackOverflow https://stackoverflow.com/questions/669932

  •  21-08-2019
  •  | 
  •  

Domanda

Sto cercando di creare una classe che non ricreare un oggetto con gli stessi parametri di input. Quando cerco di istanziare una classe con gli stessi parametri che sono stati utilizzati per creare un oggetto già esistente, voglio solo la mia nuova classe per restituire un puntatore all'oggetto già creato (costoso creati). Questo è quello che ho provato finora:

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'

Questa è la mia prima avventura nel sovrascrivendo __new__ e sono convinto non mi va su di esso nel modo giusto. Mettimi dritto, per favore.

È stato utile?

Soluzione

In primo luogo, uso superiori Caso nomi di classe in Python.

In secondo luogo, utilizzare un Fabbrica modello di progettazione per risolvere questo problema.

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]

Questo è molto più semplice rispetto a scherzare con le nuove e che hanno piscine livello di classe di oggetti.

Altri suggerimenti

Ecco un decoratore di classe per fare una classe di un multiton:

def multiton(cls):
   instances = {}
   def getinstance(id):
      if id not in instances:
         instances[id] = cls(id)
      return instances[id]  
   return getinstance

(Questa è una leggera variante della decoratrice singleton da PEP 318.)

Quindi, per rendere la vostra classe di un multiton, utilizzare il decoratore:

@multiton
class MyObject( object ):
   def __init__( self, arg):
      self.id = arg
      # other expensive stuff

Ora, se si crea un'istanza MyObject con lo stesso ID, si ottiene la stessa istanza:

a = MyObject(1)
b = MyObject(2)
c = MyObject(2)

a is b  # False
b is c  # True
Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top