代码之家  ›  专栏  ›  技术社区  ›  Paul

如何创建不使用相同输入参数重新创建对象的类

  •  2
  • Paul  · 技术社区  · 16 年前

    我正在尝试创建一个类,该类不使用相同的输入参数重新创建对象。当我试图用创建已经存在的对象所用的相同参数实例化一个类时,我只希望我的新类返回一个指向已经创建(昂贵创建)对象的指针。这就是我迄今为止所尝试的:

    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__ 我确信我做的不对。请把我弄直。

    2 回复  |  直到 14 年前
        1
  •  7
  •   S.Lott    16 年前

    首先,在Python中使用大写类名。

    第二,使用 工厂 设计模式来解决这个问题。

    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]
    

    这比玩弄新对象和拥有类级对象池要简单得多。

        2
  •  12
  •   Jerry Neumann    14 年前

    下面是一个类修饰器,用于使类成为多功能:

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

    (这是PEP 318中的单体装饰器的一个微小变体。)

    然后,要使类成为多任务类,请使用decorator:

    @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
    
    推荐文章