2011-03-03 3 views
4

사용자 정의 동작을 추가하기 위해 사전에서 상속받은 클래스가 있습니다.이 경우 유효성 검사를 위해 각 키와 값을 전달합니다. 아래 예제에서 '유효성 검사'는 단순히 메시지를 인쇄합니다.사용자 정의 dict 클래스를 Python 클래스의 __dict__ 속성으로 사용하는 동작이 이상합니다.

사전 할당은 예상대로 작동하며 항목이 dict에 추가 될 때마다 메시지를 인쇄합니다. 그러나 클래스의 __dict__ 특성으로 사용자 지정 사전 형식을 사용하려고 할 때 키/값을 사용자 지정 사전 클래스에 넣는 특성 할당은 어떻게 든 __setitem__을 우회하는 동시에 사전에 값을 삽입하는 것을 관리합니다. 키를 추가 할 수있는 정의 된 메서드).

사용자 지정 사전 :

from collections import MutableMapping 
class ValidatedDict(dict): 
    """A dictionary that passes each value it ends up storing through 
    a given validator function. 
    """ 
    def __init__(self, validator, *args, **kwargs): 
     self.__validator = validator 
     self.update(*args, **kwargs) 
    def __setitem__(self, key, value): 
     self.__validator(value) 
     self.__validator(key) 
     dict.__setitem__(self, key, value) 
    def copy(self): pass # snipped 
    def fromkeys(validator, seq, v = None): pass # snipped 
    setdefault = MutableMapping.setdefault 
    update = MutableMapping.update 

def Validator(i): print "Validating:", i 

이해가 안 클래스 수익률 행동의 __dict__ 속성으로 사용.

>>> d = ValidatedDict(Validator) 
>>> d["key"] = "value" 
Validating: value 
Validating: key 
>>> class Foo(object): pass 
... 
>>> foo = Foo() 
>>> foo.__dict__ = ValidatedDict(Validator) 
>>> type(foo.__dict__) 
<class '__main__.ValidatedDict'> 
>>> foo.bar = 100 # Yields no message! 
>>> foo.__dict__['odd'] = 99 
Validating: 99 
Validating: odd 
>>> foo.__dict__ 
{'odd': 99, 'bar': 100} 

내가 예상 한대로 동작하지 않는 이유를 설명 할 수 있습니까? 시도하고있는 방식대로 작동 할 수 있습니까?

+0

꼭해야한다면'__new__'을 제외하고는'__dict__'을 대체해서는 안된다고 생각합니다. 여기서하려고하는 것은 커스텀'__setattribute__' 메소드로 수행되어야합니다. –

+0

솔직히 말해서, 나는 정말로 "무엇인가하려합니다". 나는 유효성 검사를하는 dict 클래스를 작성하고 있었고, 단지 재미를 위해서 그것을'__dict__' 인스턴스로 사용하려고했습니다. 내 질문에 대한 이유는 정말 그것이 왜 이런 식으로 행동하는지 이해하고 주변을 둘러볼 수 있는지 여부를 이해하기 위해서입니다. – porgarmingduod

답변

5

이것은 최적화 작업입니다. __dict__에서 메타 메소드를 지원하려면 모든 단일 인스턴스 지정이 메타 메소드의 존재를 확인해야합니다. 이는 모든 속성 조회 및 할당과 같은 기본적인 작업이므로이를 확인하는 데 필요한 여분의 분기가 obj.__getattr__obj.__setattr__과 다소 중복되는 부분에 대해 전체 언어의 오버 헤드가됩니다.

+0

그래서, __dict__ 인스턴스의 메타 메소드가 절대 작동하지 않을 것이라는 뻔뻔스럽게 대답은 무엇입니까? 나는 당신이 알고있는 대답 (그리고 당신의 명성)에서 당신이 말하는 것을 정확히 알고 있다는 것을 추측 할 수 있습니까? 그리고 나는이 문제에 관해서 말하게 될 모든 대답을 받아 들일 수 있습니까? – porgarmingduod

+0

'PyObject_GenericSetAttr'의 Objects/object.c에 하드 코드되어 있습니다 : 객체에'__dict__'가 있으면'PyDict_SetItem'을 호출합니다.이 메소드는 메타 메소드를 호출하지 않고 사전 값을 직접 설정합니다. 나는 이것이'dict'의 서브 클래스가 아닌 것에'__dict__'를 설정하는 것이 허용되지 않는 이유이기도하다고 생각합니다; 예를 들어'x .__ dict__ = []'을 시도하면 예외가 발생합니다. –

+3

파이썬 문서에서 명시 적으로 언급하지 않는 버그라고 부릅니다. * class * docs (클래스 인스턴스가 아닌 *)는 특히'Cx가 C __ dict __ [ "x"]'로 변환되었다고 말합니다. 사람들이 클래스 인스턴스를 볼 수 있고 그것이 같다고 쉽게 생각할 수 있습니다. 더 명확해질 수 있습니다. http://docs.python.org/reference/datamodel.html –

관련 문제