collections.defaultdict
Python 2.5에 추가 하면 dict
의 setdefault
메소드에 대한 필요성이 크게 줄어 들었습니다 . 이 질문은 우리의 집단 교육을위한 것입니다.
setdefault
오늘날 Python 2.6 / 2.7에서 여전히 유용한 것은 무엇입니까 ?- 어떤 일반적인 사용 사례
setdefault
로 대체collections.defaultdict
되었습니까?
답변
당신이 말할 수는 defaultdict
설정 기본값에 유용 DICT를 작성하기 전에 및 setdefault
기본값을 설정하는 데 유용 동안 또는 DICT를 작성 후 .
아마도 가장 일반적인 유스 케이스 : 항목 그룹화 (정렬되지 않은 데이터, 그렇지 않으면 사용 itertools.groupby
)
# really verbose
new = {}
for (key, value) in data:
if key in new:
new[key].append( value )
else:
new[key] = [value]
# easy with setdefault
new = {}
for (key, value) in data:
group = new.setdefault(key, []) # key might exist already
group.append( value )
# even simpler with defaultdict
from collections import defaultdict
new = defaultdict(list)
for (key, value) in data:
new[key].append( value ) # all keys have a default already
때로는 dict를 만든 후 특정 키가 있는지 확인하려고합니다. defaultdict
이 경우 명시 적 액세스에서만 키를 생성하기 때문에 작동하지 않습니다. 많은 헤더와 함께 HTTP를 사용한다고 생각하십시오. 일부는 선택 사항이지만 기본값을 원합니다.
headers = parse_headers( msg ) # parse the message, get a dict
# now add all the optional headers
for headername, defaultvalue in optional_headers:
headers.setdefault( headername, defaultvalue )
답변
setdefault
이 함수와 같이 키워드 인수 dicts에 일반적으로 사용 합니다.
def notify(self, level, *pargs, **kwargs):
kwargs.setdefault("persist", level >= DANGER)
self.__defcon.set(level, **kwargs)
try:
kwargs.setdefault("name", self.client.player_entity().name)
except pytibia.PlayerEntityNotFound:
pass
return _notify(level, *pargs, **kwargs)
키워드 인수를 취하는 함수 주위의 래퍼에서 인수를 조정하는 데 좋습니다.
답변
defaultdict
새 목록처럼 기본값이 정적 일 때 좋지만 동적 인 경우에는 그다지 많지 않습니다.
예를 들어 문자열을 고유 한 정수로 매핑하려면 사전이 필요합니다. defaultdict(int)
항상 기본값으로 0을 사용합니다. 마찬가지로 defaultdict(intGen())
항상 1을 생성합니다.
대신, 나는 정규 dict을 사용했습니다.
nextID = intGen()
myDict = {}
for lots of complicated stuff:
#stuff that generates unpredictable, possibly already seen str
strID = myDict.setdefault(myStr, nextID())
참고 dict.get(key, nextID())
나중에뿐만 아니라이 값을 참조 할 수 있어야하기 때문에 불충분하다.
intGen
int를 자동으로 증가시키고 그 값을 반환하는 작은 클래스입니다.
class intGen:
def __init__(self):
self.i = 0
def __call__(self):
self.i += 1
return self.i
누군가 이것을 할 수있는 방법이 있다면 defaultdict
그것을보고 싶습니다.
답변
setdefault()
에서 기본값을 원할 때 사용 합니다 OrderedDict
. 두 가지 를 모두 수행하는 표준 Python 컬렉션은 없지만 이러한 컬렉션을 구현 하는 방법 이 있습니다.
답변
대부분의 답변 상태 setdefault
또는 defaultdict
키가 존재하지 않을 때 기본값을 설정할 수 있습니다. 그러나의 사용 사례와 관련하여 작은주의 사항을 지적하고 싶습니다 setdefault
. 파이썬 인터프리터가 실행될 때 setdefault
키가 사전에 존재하더라도 항상 함수에 대한 두 번째 인수를 평가합니다. 예를 들면 다음과 같습니다.
In: d = {1:5, 2:6}
In: d
Out: {1: 5, 2: 6}
In: d.setdefault(2, 0)
Out: 6
In: d.setdefault(2, print('test'))
test
Out: 6
보시다시피 print
, 사전에 2가 이미 존재하더라도 실행되었습니다. setdefault
예를 들어와 같은 최적화 에 사용하려는 경우 특히 중요합니다 memoization
. 에 대한 두 번째 인수로 재귀 함수 호출을 추가하면 setdefault
파이썬이 항상 함수를 재귀 적으로 호출하므로 성능을 얻지 못합니다.
메모가 언급되었으므로 메모로 함수를 향상시키는 것을 고려하는 경우 functools.lru_cache 데코레이터를 사용하는 것이 더 나은 대안입니다. lru_cache는 재귀 함수에 대한 캐싱 요구 사항을보다 잘 처리합니다.
답변
Muhammad가 말했듯이 때때로 기본값을 설정하려는 상황이 있습니다. 이에 대한 좋은 예는 데이터 구조가 먼저 채워지고 쿼리됩니다.
트라이를 고려하십시오. 단어를 추가 할 때 하위 노드가 필요하지만 존재하지 않는 경우 트리를 확장하기 위해 하위 노드를 만들어야합니다. 단어의 존재를 쿼리 할 때 누락 된 하위 노드는 해당 단어가 존재하지 않으며 단어를 만들지 않아야 함을 나타냅니다.
defaultdict는 이것을 할 수 없습니다. 대신 get 및 setdefault 메소드를 사용하는 일반 dict를 사용해야합니다.
답변
이론적으로 말하면 때로는 기본값을 설정하고 때로는하지 않으려는 setdefault
경우 여전히 유용합니다 . 실생활에서는 그런 유스 케이스를 보지 못했습니다.
그러나 흥미로운 사용 사례는 표준 라이브러리 (Python 2.6, _threadinglocal.py)에서 나옵니다.
>>> mydata = local()
>>> mydata.__dict__
{'number': 42}
>>> mydata.__dict__.setdefault('widgets', [])
[]
>>> mydata.widgets
[]
나는 사용 __dict__.setdefault
이 꽤 유용한 경우 라고 말할 것 입니다.
편집 : 발생하는 것처럼 이것은 표준 라이브러리의 유일한 예이며 주석입니다. 따라서의 존재를 정당화하는 것만으로는 충분하지 않을 수 있습니다 setdefault
. 여전히 여기에 설명이 있습니다.
객체는 속성에 속성을 저장 __dict__
합니다. 그와 같이, __dict__
속성은 객체 생성 후 언제든지 쓸 수 있습니다. 또한 사전이 아닙니다 defaultdict
. 일반적인 경우의 객체가 가지고하는 것은 분별없는 __dict__
A와 defaultdict
그 속성과 모든 법적 식별자를 가진 각 개체를 만들 것 때문이다. 따라서 __dict__.setdefault
유용하지 않은 것으로 간주되면 완전히 삭제하는 것 외에는 제거하는 Python 객체의 변경을 예측할 수 없습니다 .