developer tip

dict를 올바르게 하위 클래스로 만들고 __getitem__ 및 __setitem__을 재정의하는 방법

optionbox 2020. 10. 27. 08:05
반응형

dict를 올바르게 하위 클래스로 만들고 __getitem__ 및 __setitem__을 재정의하는 방법


일부 코드를 디버깅 중이며 특정 사전에 액세스하는시기를 알고 싶습니다. 글쎄, 실제로 dict는 몇 가지 추가 기능 을 하위 클래스로 만들고 구현하는 클래스입니다 . 어쨌든, 내가하고 싶은 것은 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'는 결국 출력을 식별하는 데 사용할 키입니다. 그런 다음 계측중인 클래스를 DictWatch대신 하위 클래스로 dict변경하고 수퍼 생성자에 대한 호출을 변경했습니다. 그래도 아무 일도 일어나지 않는 것 같습니다. 영리하다고 생각했지만 다른 방향으로 가야 할까.

도와 주셔서 감사합니다!


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

둘째, __getitem____setitem__동안에 만이라고 []액세스. 그래서 반드시 전용 액세스 확인 DictWatch을 통해를 d[key]보다는 d.get()d.set()


서브 클래 싱의 또 다른 문제 dict는 내장이를 __init__호출하지 않고 update내장이를 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

결과를 실제로 변경해서는 안됩니다 (좋은 로깅 임계 값을 위해 작동해야 함). 초기화 는 다음과 같아야합니다.

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

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

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


서브 클래 싱 UserDict또는 UserList. 이러한 클래스는 일반 반면 서브 클래 싱하기위한 것입니다 dictlist아니며, 최적화가 포함되어 있습니다.


당신이해야 할 일은

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에서만 테스트되었습니다.

참고 URL : https://stackoverflow.com/questions/2390827/how-to-properly-subclass-dict-and-override-getitem-setitem

반응형