2010-07-21 2 views
1

마법 메서드 __getitem__을 클래스의 클래스 메서드로 꾸미려고합니다. 다음은 내가 시도한 샘플입니다. 나는 classmethod 나 staticmethod 데코레이션을 사용하는 것에 신경 쓰지 않는다. 그러나 나는 그것을하는 방법을 너무 확신하지 못한다. 여기에 내가 뭘하려 : 그러나마법 메서드의 @StaticMethod 또는 @ClassMethod 장식

import ConfigParser 

class Settings(object): 
    _env = None 
    _config = None 

    def __init__(self, env='dev'): 
    _env = env 
    # find the file 
    filePath = "C:\\temp\\app.config" 

    #load the file 
    _config = ConfigParser.ConfigParser() 
    _config.read(filePath) 

    @classmethod 
    def __getitem__(cls, key): 
    return cls._config.get(cls._env, key) 

    @classmethod 
    def loadEnv(cls, env): 
    cls._env = env 

, 나는 다음과 같은 오류가 Settings['database']를 호출 할 때.

Traceback (most recent call last): 
File "<stdin>", line 1, in <module> 
TypeError: expected Array[Type], got str 

누구든지 내가 뭘 잘못하고 있는지 말할 수 있습니까? 또한 누군가가 이것을 할 수있는 더 좋은 방법이 있다면 제안 할 수 있습니까? 필자는 MetaClasses를 사용해 보았지만, 거의 성공하지 못했습니다 (파이썬도 잘 모름).

class Meta(type): 
    def __getitem__(*args): 
    return type.__getitem__(*args) 

class Settings(object): 
    __metaclass__ = Meta 

미리 감사드립니다.

+0

관련되지 않음,하지만 당신은 self._env'과'자기'에 할당 잊고 있습니다. 당신의'__init__' 메소드에서'_config'를 사용하십시오. 클래스 레벨의 속성'_env'와'_config'도 쓸모가 없습니다. –

답변

1

알렉스 (완전히 올바른) 답변 외에도 실제로 여기서 무엇을하고 싶은지 확실하지 않습니다. 지금은 클래스를 인스턴스화 할 때 config를로드하려고합니다. 해당 _config를 클래스 개체에 할당하면 클래스의 모든 인스턴스가 동일한 구성을 공유한다는 것을 의미합니다 (다른 인스턴스를 만들면 모든 기존 인스턴스가 최신 구성을 가리 키도록 변경됩니다). 을 사용하려고하는 이유는 무엇입니까? 클래스의 특정 인스턴스 대신이 구성에 액세스하려면? 한 가지 구성 만있는 경우에도 클래스 인스턴스를 사용하는 것이 훨씬 더 편리합니다 (이해할 수 있습니다!). 당신은 모듈 - 세계에서이 인스턴스를 저장하고 전화 '설정'만약 당신이 좋아하면 할 수 귀하의 질문에

class _Settings(object): 
    def __init__(self, fname): 
     self._config = ... 
    ... 

Settings = _Settings('/path/to/config.ini') 
+0

이것은 갈 길입니다. 클래스를 인스턴스처럼 동작하게 만들고 싶다면 먼저 인스턴스를 사용하는 것이 좋습니다. –

+0

당신이 옳을 수도 있습니다. 설정을 전역 적으로 액세스 가능하게하려고합니다. 일단 설정 환경을 정의하면, 그 설정에 대한 설정 (db, server, timeout)을로드하고 싶습니다. –

4

파이썬은 항상 인스턴스가 아닌 클래스에서 __getitem__ 및 기타 마법 메서드를 찾습니다. 따라서 예를 들어, __getitem__을 메타 클래스로 정의하면 클래스를 클래스로 색인 할 수 있습니다. 그러나 위임하지 않아도 아무 것도 정의 할 수없는 것처럼 __getitem__이 아닌 __getitem__type에 위임하여 정의 할 수 없습니다. 물론 다른 존재하지 않는 방법 ;-). 당신은 그런 Settings으로 인덱스에 클래스를 필요로하는 경우

따라서, 사용자 정의 메타 클래스는 실제로 __getitem__를 정의해야합니다,하지만 당신이 원하는 작업을 수행 명시 적 코드로 정의해야 함 - return cls._config.get 당신이 원하는.

편집 : ... 나에게 간단한 예를주게 : 물론

>>> class MyMeta(type): 
... def __getitem__(cls, k): 
...  return cls._config.get(k) 
... 
>>> class Settings: 
... __metaclass__ = MyMeta 
... _config = dict(foo=23, bar=45) 
... 
>>> print Settings['foo'] 
23 

, 즉 그것에 거기 모두, 그것은 건축가에 클래스 색인 "로이 코드 어리석은 것 인 경우 "- 클래스는 상태와 메서드가있는 인스턴스를 더 가지고 있어야합니다. 그렇지 않으면 대신 모듈을 코딩해야합니다. 그리고 "적절한"액세스가 특정 인스턴스가 아닌 전체 클래스를 인덱싱해야하는 이유는 분명하지 않습니다. 하지만 이런 식으로 구조화하려는 좋은 설계 이유가 있다고 가정하면 칭찬을하고 그냥 을 어떻게 표시할까요?과 같은 구조를 구현할 수 있습니다.

+0

나도 같은 시간대에있을 때 나는 그것을 싫어 같이, GRR : 내가 클래스 메타 (유형)에 메타 클래스를 변경 시도 –

+0

: \t 데프 __getitem __ (CLS, 키) : \t \t 인쇄 '메타 'CLS'키를 GetItem : '키 \t \t 반환 cls._config.get (cls._env, 키) 그러나, 나는 여전히 메타의 getItem 얻을 <클래스'. __main __을 설정 '> 키 : 데이터베이스 추적 (가장 최근의 마지막 통화) : 파일 "", 줄 1, 파일 "", 줄 4, __getitem__ AttributeError : 'NoneType'객체에 'get'속성이 없습니다. 아이디어가 있으십니까? –

+0

@Bobby, 코드에서 주석을 읽을 수 없다 - 예제 코드를 보면 잘 작동하며, 작동 코드와 작동하지 않는 코드 사이의 차이점을 발견 할 수있다 (또는, 귀하의 질문을 편집하십시오. ** 의견이 아니라 ** "내 주장과 동일하다고 생각되는 코드"를 추가하면 작동하지 않습니다. 그러면 우리가 당신을 위해 차이점을 발견 할 수 있는지 알게 될 것입니다. –