2012-11-14 3 views
2

어떻게 이런 상황에 처하게되었는지 묻지 마십시오. ccollection이라는 클래스가 있다고 가정 해 보겠습니다.클래스의 모든 속성 인쇄

이 클래스는 런타임에 다음과 같은 특성이 있습니다 : 전술 한 바와 같이

ccollection.a.b.x = 1 
ccollection.a.b.y = 3 
ccollection.a.b.z = 4 
... 
ccollection.a.c = 3 
ccollection.b = 3 

이 클래스는 동적으로 설정 될 것입니다. 그래서 클래스의 속성을 직접 알 수있는 방법은 없습니다. 이제

내가 예를 들어,이 클래스의 모든 속성을 인쇄하고 싶습니다 :

ccollection.a.b 내가 당신이 얻을 생각

ccollection.a.b.x = 1 
ccollection.a.b.y = 3 
ccollection.a.b.z = 4 
ccollection.a.c = 3 

를 인쇄해야

ccollection.a.b.x = 1 
ccollection.a.b.y = 3 
ccollection.a.b.z = 4 

ccollection.a를 인쇄한다 아이디어. 각 인쇄는 같은 레벨 아래의 모든 요소 인쇄를 시작해야합니다. 재귀 적으로 모든 속성 (나무와 같은 데이터 구조)을 가로 지르는 방법을 찾고 있습니다.

+0

'collection.a'의 유형은 무엇입니까? 'collection.a.b'는'collection' 객체의 속성이 아니고'collection.a'의 속성이기 때문에 묻습니다. 원하는 방식으로 작동하려면 사용자 정의'__str__' 또는'__repr__' 메소드로 여러 클래스를 만들어야 할 수도 있습니다. – Blckknght

+0

@Blckknght, ccollection.a.b.x = 1에서 a 자체는 ccollection이고, b는 또한 ccollection입니다. x가 1로 설정됩니다. – theAlse

+0

Ok. 어떻게 속성을 작성하고 있습니까? 방금 직접 할당하고 있습니까 (예 :'ccollection.a = ccollection()')? 또는 주어진 인스턴스가 어떤 속성을 가져야 하는지를 알 수있는 특정 방법이 있습니까? 그렇지 않다면,'dir'을 사용할 수 있습니다. 그러나 그 방법에 포함될 다른 방법들과 다른 방법들을 제거하는 것은 고통이 될 것입니다. – Blckknght

답변

1

이 상황은 실제로 리팩토링을 요구합니다. 컨테이너로 설계되지 않은 개체를 사용 중입니다. 대신, dict 또는 dict에서 상속하는 클래스와 같은 컨테이너를 사용하십시오. 현재 설정을 사용해야하는 경우


, 나는 가장 유망한 방법은 디렉토리를 사용하여 표시 Blckknght에 동의합니다.

class CCollection(object): 
    def get_children_strings(self): 
    list_of_strings = [] 
    for attr_name in dir(self): 
     if attr_name not in dir(CCollection()): 
     attr = getattr(self, attr_name) 
     if hasattr(attr, 'get_children_strings'): 
      list_of_strings.extend(["." + attr_name + child_string for child_string in attr.get_children_strings()]) 
     else: 
      list_of_strings.append("." + attr_name + " = " + str(attr)) 
    return list_of_strings 

    def print_tree(self, prefix): 
    print [prefix + s for s in self.get_children_strings()] 

그럼 당신은

m = CCollection() 
m.a = CCollection() 
m.a.b = CCollection() 
m.a.b.x = 1 
m.a.b.y = 2 
m.a.c = 3 
m.d = 4 

m.print_tree("m") 
m.a.print_tree("m.a") 
m.a.b.print_tree("m.a.b") 

과 출력을 얻을 수 있습니다 :

>>> m.print_tree("m") 
['m.a.b.x = 1', 'm.a.b.y = 2', 'm.a.c = 3', 'm.d = 4'] 
>>> m.a.print_tree("m.a") 
['m.a.b.x = 1', 'm.a.b.y = 2', 'm.a.c = 3'] 
>>> m.a.b.print_tree("m.a.b") 
['m.a.b.x = 1', 'm.a.b.y = 2'] 

이 더, 당신은 아마 트리 탐색 기능을 가진 클래스를 사용하고자하는 것입니다 촬영합니다.부모 노드를 가져 오는 함수가 있고, 루프가 없다는 보장이 있고, 노드 이름을 포함하는 클래스 변수가 있으면 print_tree 함수에 prefix 인수를 통해 현재 전달되는 정보를 자동으로 생성 할 수 있습니다.

+0

내 오래된 질문 중 하나이지만 훌륭한 대답은 그다지 적습니다. – theAlse

0

특성 액세스가있는 구조와 같은 트리를 원하는 것처럼 보입니다. 이것은 dict을 서브 클래스화한 다음 적절한 __getattr____setattr__을 설정하여 원하는 액세스 API를 얻는 동시에 원하는 인쇄를 할 수 있습니다.

또한 __str__을 재정의하면 원하는대로 정확하게 인쇄 할 수 있습니다.

편집 :

빨리 설명하려면 다음과 같이하십시오.

class DictTree(object): 
    _children = {} 

    def __getattr__(self, name): 
     if not name in self._children: 
      self._children[name] = DictTree() 
     return self._children[name] 

    def __setattr__(self, name, v): 
     self._children[name] = v 

위의 작품은 당신이 원하는 액세스 및 API 인터페이스를 제공하지만, 그것을 인쇄 할 때 나는 때문에 어떻게 __getattr__이 작동의 RuntimeError: maximum recursion depth exceeded를 얻을. 위의 코드를 수정하지 않으면이 문제가 발생하지 않고 원하는 코드를 얻을 수 있습니다. 수정 프로그램에는 __str__ 메서드가 포함됩니다.

+0

나는 그것이 그렇게 할 수 있다고 확신한다. (나는 어떻게 모르겠다.) 나는이 나무 같은 구조를 재귀 적으로 가로 지르는 길을 찾고 있었다. 성공적으로 트리를 탐색 할 수 있지만 항상 상위 수준이 __str__을 (를) 상실합니다. – theAlse

+0

트리에서 재귀 호출하기 전에 현재 수준의 값을 인쇄해야합니다. – sean

+0

모든 DictTree 객체가 동일한 (단일) 사전을 사용할 것이기 때문에 클래스 함수 밖에서'_children' 클래스 변수로 사전을 인스턴스화하기를 원하지는 않습니다. 예를 들어 [this so answer] (http://stackoverflow.com/a/6021050/783037)를 참조하십시오. 대신, 예를 들어'__init__ '에 각 인스턴스에 대한 새로운 사전을 만들고 싶습니다. 불행히도, 변경된'__setattr__ '때문에 그것은 어렵습니다. – beaslera