2017-03-21 1 views
0

나는 다음과 같은 클래스를 생성 메타 정보를 포함하는 메타 정보 ('meta_dict'라고 함).전화 클래스 메서드는 한 번만

내가 원했던 것은 다음과 같다 : 사전 'meta_dict'는 변경 가능해야한다.

df = SavTool("somepath") 
df.meta_dict["new_key"] = "new_value" 
print df.meta_dict["new_key"] 

을하지만 무슨 일 나는 구문 'df.meta_dict'라고하는 방법 'meta_dict'와 loader.Loader에서 원래 'meta_dict'를 사용할 때마다이 같은 돌려 주어집니다 : 즉, 다음과 같은 작업을해야합니다 'df.meta_dict'는 변경할 수 없습니다. 따라서 구문은 "KeyError : 'new_key'"로 연결됩니다. 'meta_dict'는 한 번만 호출되고 두 번째/세 번째 호출/사용되면 다시는 호출되지 않습니다. 두 번째/세 번째 ... 시간 'meta_dict'는 속성 (이 경우 사전)이어야합니다.

어떻게 해결할 수 있습니까? 어쩌면 클래스의 전체 디자인이 좋지 않아 변경해야합니다 (클래스를 사용하는 것이 처음입니다). 귀하의 답변 주셔서 감사합니다!

답변

1

loader.Loader으로 전화하면 매번 사전의 새 인스턴스가 생성됩니다. @property은 아무 것도 캐시하지 않으므로 호출자의 깨끗한 인터페이스를 위해 복잡한 getter를 래핑하는 데 편리합니다.

이와 비슷한 기능이 작동합니다. path 변수를 올바르게 업데이트하여 클래스에 올바르게 바인딩되고 path 속성에 올바르게 반환됩니다.

import loader 
import pandas 

class SavTool(pd.DataFrame): 

    def __init__(self, path): 
     pd.DataFrame.__init__(self, data=loader.Loader(path).data) 
     self._path = path 
     self._meta_dict = loader.Loader(path).dict 

    @property 
    def path(self): 
     return self._path 

    @property 
    def meta_dict(self): 
     return self._meta_dict 

    def update_meta_dict(self, **kwargs): 
     self._meta_dict.update(kwargs) 

단지 변수를 캐시하는 또 다른 방법은 hasattr을 사용하는 것입니다 : 당신의 대답에

@property 
def meta_dict(self): 
    if not hasattr(self, "_meta_dict"): 
     self._meta_dict = loader.Loader(path).dict 
    return self._meta_dict 
+0

감사합니다! 당신은 나를 많이 도왔습니다. :) 방금 판다 DataFrame을 inistializing하는 것 외에도 (__init__에서 inistializing 할 때) 인스턴스에 다른 속성을 추가 할 수 있다는 것을 알지 못했습니다. – John

+0

@ 존 : 대단히 환영합니다. 캐싱에 대한 바로 가기 "해킹"으로 답변을 업데이트했습니다. – sdolan

+0

한 가지 알아둬야 할 것은'__init__'에서 기본 클래스 (이 경우'DataFrame')에 속성을 추가하면 몇 가지 불쾌한 버그가 발생한다는 것입니다. 팬더는 오픈 소스이기 때문에 언제든지 다시 확인할 수 있습니다 ... 행운을 빕니다! – sdolan

관련 문제