일부 코드를 디버깅 중이며 특정 사전에 액세스하는시기를 알고 싶습니다. 글쎄, 실제로 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
답변
서브 클래 싱 UserDict
또는 UserList
. 이러한 클래스는 일반 반면 서브 클래 싱하기위한 것입니다 dict
및 list
아니며, 최적화가 포함되어 있습니다.
답변
그것은 결과를 실제로 변경해서는 안됩니다 (좋은 로깅 임계 값을 위해 작동해야 함) : init 는 다음과 같아야합니다.
def __init__(self,*args,**kwargs) : dict.__init__(self,*args,**kwargs)
대신 DictWatch ([(1,2), (2,3)]) 또는 DictWatch (a = 1, b = 2)로 메서드를 호출하면 실패하기 때문입니다.
(또는 더 나은, 이것에 대한 생성자를 정의하지 마십시오)
답변
당신이해야 할 일은
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에서만 테스트되었습니다.
답변
Andrew Pate 답변을 완성하기 위해 다음 dict
과 같은 차이점을 보여주는 예가 있습니다 UserDict
.
dict를 올바르게 덮어 쓰는 것은 까다 롭습니다.
class MyDict(dict):
def __setitem__(self, key, value):
super().__setitem__(key, value * 10)
d = MyDict(a=1, b=2) # Bad! MyDict.__setitem__ not called
d.update(c=3) # Bad! MyDict.__setitem__ not called
d['d'] = 4 # Good!
print(d) # {'a': 1, 'b': 2, 'c': 3, 'd': 40}
UserDict
에서 상속 collections.abc.MutableMapping
하므로 사용자 정의하기가 훨씬 쉽습니다.
class MyDict(collections.UserDict):
def __setitem__(self, key, value):
super().__setitem__(key, value * 10)
d = MyDict(a=1, b=2) # Good: MyDict.__setitem__ correctly called
d.update(c=3) # Good: MyDict.__setitem__ correctly called
d['d'] = 4 # Good
print(d) # {'a': 10, 'b': 20, 'c': 30, 'd': 40}
마찬가지로, 당신은 단지 구현해야 __getitem__
자동으로와 호환되도록 key in my_dict
, my_dict.get
…
참고 : UserDict
의 서브 클래스가 아닌 dict
, 그래서 isinstance(UserDict(), dict)
실패 할 것이다 (하지만 isinstance(UserDict(), collections.abc.MutableMapping)
작동합니다)
답변
