2009-03-21 23 views
2

동일한 입력 매개 변수를 사용하여 개체를 다시 만들지 않는 클래스를 만들려고합니다. 이미 존재하는 객체를 만드는 데 사용 된 것과 동일한 매개 변수를 사용하여 클래스를 인스턴스화하려고하면 새 클래스가 이미 작성된 객체 (비싼 값으로 생성 된 객체)에 대한 포인터를 반환하기 만하면됩니다. 이것은 내가 지금까지 시도한 것입니다 :동일한 입력 매개 변수를 사용하여 개체를 다시 만들지 않는 클래스를 만드는 방법

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__에 처음으로 벤처와 내가 올바른 방법 그것에 대해 않을거야 확신 해요. 나를 똑바로 세워 줘.

답변

8

먼저 파이썬에서 대문자 클래스 이름을 사용하십시오.

두 번째로이 문제를 해결하려면 공장 디자인 패턴을 사용하십시오.

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] 

이것은 새롭고 클래스 수준의 개체 풀로 속이는 것보다 훨씬 간단합니다.

+0

정확하게 이것을 수행하는 가장 좋은 방법입니다. 완벽하게 제안. – mpeterson

+1

'__new__'을 사용하면 실제로 다른 클래스를 도입하는 것과는 달리/그것을 수행하는 파이썬 적 방법이 될 것입니다. 해결책은 관용적 인 Java입니다. 또한 괄호 안에 공백을 넣지 말고 Python에서 camelCase 메서드 이름을 사용하지 마십시오. –

11

여기 클래스에게 멀티 톤 만들기 위해 클래스 장식입니다 :

이 그런 다음 A 급 멀티 톤 만들기 (이 PEP (318)에서 싱글 장식의 약간의 변형입니다)

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

을,

: 동일한 ID로 MyObject를 인스턴스화하는 경우, 동일한 인스턴스를 가져 지금

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

: 데코레이터를 사용

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

a is b # False 
b is c # True 
+0

이것은 훨씬 더 깨끗하고, S.Lott의 제안처럼 효율적이고 간단한 솔루션입니다. –

+0

@ErikAllik, 당신은 "''__new__ '을 사용하는 것은 실제로 그것을 수행하는 비열한 방법이 될 것입니다." '__new__'을 사용하는 @ Jerry의 솔루션을 선호합니까? – kuzzooroo

+0

@kuzzooroo : 나는 예스 - 제리의 해결책이 덜 마법적이고 더 똑 바르며 Pythonic이라고 같은 말을 할 것이다. –