2012-12-31 4 views
2

파이썬 3.3을 사용하여 Test 클래스를 TestManager이라는 다른 클래스에 바인드하여 관리자가 Test의 인스턴스를 만들고 이후에 액세스 할 수있게 저장하려고합니다.초기화시 클래스의 인스턴스를 만들고 저장하는 방법은 무엇입니까?

> t = Test.objects.get(id=3) 
> t.name 
# Returns 'Name 3' 

트릭은 내 컬렉션이다 : 간단히 말해서 (나는 ..., 파이썬 쉘을 의미), 나는이 작업을 수행 할 수 있도록하려면에서

은 ( name를 가정하는 것은 Test의 속성) 객체는 처음에는 (어떤 사용자도 아닌) 생성되고 수정되거나 삭제되지 않으며 레코드가 제거되거나 편집된다는 의미에서 "정적"컬렉션입니다. 고쳐졌습니다. 그래서 여기에 내가 노력 코드입니다 :

class TestManager: 
    def __init__(self, *args, **kwargs): 
     self._tests = [Test(name='Name {}'.format(i)) for i in range(100)] 

    def get(self, id): 
     return self._tests[id] 

class Test: 
    objects = TestManager() 

    def __init__(self, name=''): 
     self.name = name 

Aaaand, 예상대로 NameError: global name 'Test' is not defined 인해 원형 초기화합니다. 이상적으로는 (__init__() 대신) 목록에 요소를 추가하는 관리자에서 create() 메서드를 가져야하지만 이는 관리자가 아니라 다른 곳에서 작성이 완료되었음을 의미합니다.

"최상의"해결책은 지금까지 get() 메서드가 처음에는 목록이 비어 있는지 확인하여 fill_the_damn_list() 메서드를 호출하는 것이지만 매우 나에게 해가되는 것처럼 보입니다. 이를 수행하는 또 다른 방법은 목록 대신 사전을 사용하고 처음에는 get()에서 인스턴스를 생성하는 것입니다. 후자의 이점은 쓸데없는/절대로 get() -ed 인스턴스를 만들지는 않지만 전체적으로 백 개만있는 것이므로 정말로 중요하지 않으며이 솔루션의 hackish-ness는 완전히 동일하게 보입니다. 나에게 ...

파이썬 (내가 충분히 명확하지 않다면 ...)에 익숙하지 않기 때문에, 그렇게 할 수있는 더 좋은 방법이 있는지, 그리고 그것을 간결하게 유지할 수 있을지 궁금하다. 또한 필요한 경우 리팩토링하는 것이 좋습니다. 그러나 아직 더 좋은 해결책을 찾지 못했습니다.

+0

이 순환 참조는 무엇에 좋은가요? "TestManager"에 테스트 목록이 있으면 충분하지 않아야합니까? – Hyperboreus

+1

클래스 생성 후'objects' 속성을 할당하십시오. 클래스 코드를'None'으로 설정하고'Test' 클래스 코드 바로 다음에'TestManager()를 설정하십시오. – Bakuriu

+1

이 디자인은'object' 공장과 비슷한 모양입니다. 그것이 쓰여지는 방법을 많이 이해하지는 못합니다. _TestManager_는 컬렉션에 색인을 생성하는 데 사용되어야하며이 컬렉션에 도착하려면 _Test_ 클래스를 거칠 필요가 없습니다. – sean

답변

1

귀하의 디자인은 조금 이상한 것 같다 - Test 클래스는 TestManger 인스턴스에 대한 참조를해야하는 이유는 불분명하다. 그럼에도 불구하고, 나는 다음과 같은 일이 일어날 것이라고 생각한다. 그것은 Test 클래스의 objects 클래스를 생성하기 위해 메타 클래스를 사용하고 TestManger 인스턴스에 원하는 _tests 속성을 추가합니다.이 모든 것은 다소 특이한 답변입니다. 피팅입니다.;-)

class TestManager: 
    def __init__(self, *args, **kwargs): 
     print('creating TestManager') 

    def get(self, id): 
     return self._tests[id] 

class TestMetaClass(type): 
    def __new__(mcl, name, bases, classdict): 
     # add an "objects" attribute to the class being created 
     classdict['objects'] = tm = TestManager() 
     cls = type.__new__(mcl, name, bases, classdict) 
     # add a "_tests" attribute to the TestManager instance just created 
     # (can't use class's name, since it hasn't been returned yet) 
     tm._tests = [cls(name='Name {}'.format(i)) for i in range(100)] 
     return cls 

class Test(metaclass=TestMetaClass): 
    def __init__(self, name=''): 
     self.name = name 

t = Test.objects.get(3) 
print(t.name) 
+0

우선, 나는 중학교 개발자이므로 디자인 실력을 향상시켜야한다는 점에 전적으로 동의합니다. 그래서 내가하고 배우는 것과 같은 경험이 많은 사람들로부터 의견이나 조언을 얻습니다. 질문을 단순하게 유지하려했지만 약간의 문맥을 제공해야했습니다. 장고를 사용하여 온라인 카드 게임을 만들고 있는데 카드 인스턴스를 데이터베이스에 저장하지 않고 추적해야합니다. 'Card.objects.get()'문법은 또한 Django 모델 객체와 나의'Card' 객체의 레코드에 접근하는 투명한 방법을 가지고 있습니다. 나는 너를 완전히 잘못 알고 있느냐? – astorije

+0

@ JérémieAstori : 나는 장고에 익숙하지 않다. 그리고 당신이하려는 일을하는 데있어 제약이있다. 즉, 주요 어려움은 컨테이너에 (또는) 컨테이너/콜렉션 (예 :'TestManager')을 인식하도록 객체를 만들고 싶다는 것입니다. [순환 종속성] (http : // en .wikipedia.org/wiki/Circular_dependency). 일반적으로 컬렉션이 정적이기 때문에 많은 문제를 피할 수는 있지만 다른 문제도 발생할 수 있습니다. 왜 그냥'Deck' 컨테이너를 만들고'TestManager'를 만들어서 사용할 수 없습니까? – martineau

1

나는 sean의 의견에 완전히 동의합니다. 귀하의 디자인은 이상합니다. 심지어 그것을 사용하기 전에. 어쨌든, 당신이 그것을하고 싶다면 당신은 많은 다른 방법을 사용할 수 있습니다.

간단한 방법 :

class TestManager: 
    def __init__(self, *args, **kwargs): 
     self._tests = [Test(name='Name {}'.format(i)) for i in range(100)] 

    def get(self, id): 
     return self._tests[id] 

class Test: 
    objects = None 

    def __init__(self, name=''): 
     self.name = name 

Test.objects = TestManager() 

타 접근 방식은 장식을 사용 할 수 있습니다 : TestManager은 싱글 인 경우,하지만 당신이 단순히 싱글이 아닌 경우

>>> class TestManager(object): 
...  def __init__(self, *args, **kwargs): 
...    self._tests = [] 
...  def init_class(self, cls): 
...    self._tests = [cls(name='Name {}'.format(i)) for i in range(100)] 
...    cls.objects = self 
...    return cls 
...  def get(self, id): 
...    return self._tests[id] 
... 
>>> manager = TestManager() 
>>> @manager.init_class 
... class Test(object): 
...  def __init__(self, name=''): 
...    self.name = name 
... 
>>> manager.get(5) 
<__main__.Test object at 0x7f4319db8110> 

위의 조리법 작동 클래스 인스턴스에 액세스하기 전에 TestManager.init_class(TheClass)에 전화하는 것을 잊지 말고 코드에서 아무 곳에서나 수행 할 수 있습니다.

당신은이에 대한 게터를 사용할 수 있습니다

>>> class TheGetter(object): 
...  def __init__(self, cls): 
...    self._cls = cls 
...    self._inst = None 
...  def __get__(self, inst, owner): 
...    if self._inst is None: 
...      self._inst = self._cls() 
...    return self._inst 
... 
>>> class Test(object): 
...  objects = TheGetter(TestManager) 
...  def __init__(self, name): 
...    self.name = name 
... 
>>> Test.objects.get(5) 
<__main__.Test object at 0x7f431690c0d0> 
+0

나는 나의 디자인에 대한 귀하의 의견에 동의하며, 따라서 martineau의 답변에 대한 몇 가지 문맥 세부 사항을 주셨습니다. 이번에는 더 명확 해지기를 바랍니다 ...하지만이 디자인에 관해서 의견이 있으면, 제안에 대해 열려 있습니다 !! :-) – astorije

관련 문제