복붙노트

[PYTHON] dict를 적절하게 서브 클래스 화하고 __getitem__ & __setitem__을 재정의하는 방법

PYTHON

dict를 적절하게 서브 클래스 화하고 __getitem__ & __setitem__을 재정의하는 방법

일부 코드를 디버깅하고 특정 사전에 액세스 할 때 알아 보려고합니다. 글쎄, 실제로 하위 클래스는 dict이고 몇 가지 추가 기능을 구현하는 클래스입니다. 어쨌든, 내가하고 싶은 일은 서브 클래스를 직접 작성하고 __getitem__ 및 __setitem__을 추가하여 디버깅 출력을 생성하는 것입니다. 지금 당장

class DictWatch(dict):
    def __init__(self, *args):
        dict.__init__(self, args)

    def __getitem__(self, key):
        val = dict.__getitem__(self, key)
        log.info("GET %s['%s'] = %s" % str(dict.get(self, 'name_label')), str(key), str(val)))
        return val

    def __setitem__(self, key, val):
        log.info("SET %s['%s'] = %s" % str(dict.get(self, 'name_label')), str(key), str(val)))
        dict.__setitem__(self, key, val)

'name_label'은 결국 출력을 식별하는 데 사용할 키입니다. 그런 다음 클래스를 변경하여 dict 대신 DictWatch를 서브 클래스 화하고 superconstructor에 대한 호출을 변경했습니다. 아직도, 아무 것도 일어나지 않는 것 같습니다. 나는 영리하다고 생각했지만, 나는 다른 방향으로 가야하는지 궁금해.

도와 주셔서 감사합니다!

해결법

  1. ==============================

    1.당신이하고있는 일은 절대적으로 효과가 있어야합니다. 귀하의 클래스를 테스트하고 로그 문에없는 여는 괄호를 제외하고 잘 작동합니다. 내가 생각할 수있는 것은 두 가지뿐입니다. 첫째, 로그 문 출력이 올바르게 설정 되었습니까? 스크립트 상단에 logging.basicConfig (level = logging.DEBUG)를 넣어야 할 수도 있습니다.

    당신이하고있는 일은 절대적으로 효과가 있어야합니다. 귀하의 클래스를 테스트하고 로그 문에없는 여는 괄호를 제외하고 잘 작동합니다. 내가 생각할 수있는 것은 두 가지뿐입니다. 첫째, 로그 문 출력이 올바르게 설정 되었습니까? 스크립트 상단에 logging.basicConfig (level = logging.DEBUG)를 넣어야 할 수도 있습니다.

    둘째, __getitem__ 및 __setitem__은 [] 액세스 중에 만 호출됩니다. 따라서 d.get () 및 d.set ()보다는 d [key]를 통해 DictWatch에 액세스해야합니다.

  2. ==============================

    2.dict를 하위 클래스화할 때 또 다른 문제는 내장 된 __init__이 update를 호출하지 않으며 내장 된 업데이트가 __setitem__을 호출하지 않는다는 것입니다. 따라서 모든 setitem 작업을 __setitem__ 함수를 통해 수행하려면 자신이 호출되는지 확인해야합니다.

    dict를 하위 클래스화할 때 또 다른 문제는 내장 된 __init__이 update를 호출하지 않으며 내장 된 업데이트가 __setitem__을 호출하지 않는다는 것입니다. 따라서 모든 setitem 작업을 __setitem__ 함수를 통해 수행하려면 자신이 호출되는지 확인해야합니다.

    class DictWatch(dict):
        def __init__(self, *args, **kwargs):
            self.update(*args, **kwargs)
    
        def __getitem__(self, key):
            val = dict.__getitem__(self, key)
            print 'GET', key
            return val
    
        def __setitem__(self, key, val):
            print 'SET', key, val
            dict.__setitem__(self, key, val)
    
        def __repr__(self):
            dictrepr = dict.__repr__(self)
            return '%s(%s)' % (type(self).__name__, dictrepr)
    
        def update(self, *args, **kwargs):
            print 'update', args, kwargs
            for k, v in dict(*args, **kwargs).iteritems():
                self[k] = v
    
  3. ==============================

    3.결과를 실제로 변경해서는 안됩니다 (양호한 로깅 임계 값의 경우 효과가 있음). init은 다음과 같아야합니다.

    결과를 실제로 변경해서는 안됩니다 (양호한 로깅 임계 값의 경우 효과가 있음). init은 다음과 같아야합니다.

    def __init__(self,*args,**kwargs) : dict.__init__(self,*args,**kwargs) 
    

    대신 DictWatch ([(1,2), (2,3)]) 또는 DictWatch (a = 1, b = 2)를 사용하여 메서드를 호출하면 실패합니다.

    (또는, 더 나은, 이것에 대한 생성자를 정의하지 마십시오)

  4. ==============================

    4.UserDict 또는 UserList의 하위 클래스를 고려하십시오. 이러한 클래스는 하위 클래스로 만들어 지지만 일반 dict 및 list는 최적화되지 않습니다.

    UserDict 또는 UserList의 하위 클래스를 고려하십시오. 이러한 클래스는 하위 클래스로 만들어 지지만 일반 dict 및 list는 최적화되지 않습니다.

  5. ==============================

    5.당신이해야 할 일은

    당신이해야 할 일은

    class BatchCollection(dict):
        def __init__(self, inpt={}):
            super(BatchCollection, self).__init__(inpt)
    

    개인적인 사용을위한 샘플 사용법

    ### EXAMPLE
    class BatchCollection(dict):
        def __init__(self, inpt={}):
            super(BatchCollection, self).__init__(inpt)
    
        def __setitem__(self, key, item):
            if (isinstance(key, tuple) and len(key) == 2
                    and isinstance(item, collections.Iterable)):
                # self.__dict__[key] = item
                super(BatchCollection, self).__setitem__(key, item)
            else:
                raise Exception(
                    "Valid key should be a tuple (database_name, table_name) "
                    "and value should be iterable")
    

    참고 : python3에서만 테스트되었습니다.

  6. from https://stackoverflow.com/questions/2390827/how-to-properly-subclass-dict-and-override-getitem-setitem by cc-by-sa and MIT license