collections.defaultdict는 어떻게 작동합니까?
파이썬 문서에서 예제를 읽었지만 여전히이 방법의 의미를 알 수는 없습니다. 누군가 도울 수 있습니까? 파이썬 문서에서 두 가지 예가 있습니다.
>>> from collections import defaultdict
>>> s = 'mississippi'
>>> d = defaultdict(int)
>>> for k in s:
... d[k] += 1
...
>>> d.items()
[('i', 4), ('p', 2), ('s', 4), ('m', 1)]
과
>>> s = [('yellow', 1), ('blue', 2), ('yellow', 3), ('blue', 4), ('red', 1)]
>>> d = defaultdict(list)
>>> for k, v in s:
... d[k].append(v)
...
>>> d.items()
[('blue', [2, 4]), ('red', [1]), ('yellow', [1, 3])]
매개 변수 int
와 list
무엇을위한?
일반적으로 파이썬 사전 KeyError
은 현재 사전에없는 키로 항목을 가져 오려고하면 a를 던집니다 . defaultdict
달리 단순히 액세스하려고하는 것이 모든 항목 (물론 제공 그들은 아직 존재하지 않는)를 작성합니다. 이러한 "기본"항목을 만들려면 생성자에 전달하는 함수 객체를 호출합니다 (보다 정확하게는 함수 및 유형 객체를 포함하는 임의의 "호출 가능한"객체입니다). 첫 번째 예의 경우 기본 항목은을 사용하여 만들어지며 int()
정수 객체가 반환됩니다 0
. 두 번째 예의 경우 기본 항목은을 사용하여 만들어지며 list()
새 빈 목록 객체가 반환됩니다.
defaultdict
사전에 키가 없으면 KeyError
던져지는 대신 새 항목이 작성 됨을 의미합니다 . 이 새 항목의 유형은 defaultdict의 인수로 제공됩니다.
예를 들면 다음과 같습니다.
somedict = {}
print(somedict[3]) # KeyError
someddict = defaultdict(int)
print(someddict[3]) # print int(), thus 0
defaultdict
"표준 사전에는 값을 검색하고 값이 존재하지 않는 경우 기본값을 설정하기위한 setdefault () 메소드가 포함되어 있습니다. 반대로, defaultdict
컨테이너가 초기화 될 때 호출자가 기본값 (반환 될 값)을 지정할 수있게합니다."
예제로 파이썬 표준 라이브러리 에서 Doug Hellmann이 정의한대로
defaultdict를 사용하는 방법
defaultdict 가져 오기
>>> from collections import defaultdict
defaultdict를 초기화하십시오
전달하여 초기화
첫 번째 인수로 호출 가능 (필수)
>>> d_int = defaultdict(int)
>>> d_list = defaultdict(list)
>>> def foo():
... return 'default value'
...
>>> d_foo = defaultdict(foo)
>>> d_int
defaultdict(<type 'int'>, {})
>>> d_list
defaultdict(<type 'list'>, {})
>>> d_foo
defaultdict(<function foo at 0x7f34a0a69578>, {})
>>> d_int = defaultdict(int, a=10, b=12, c=13)
>>> d_int
defaultdict(<type 'int'>, {'a': 10, 'c': 13, 'b': 12})
또는
>>> kwargs = {'a':10,'b':12,'c':13}
>>> d_int = defaultdict(int, **kwargs)
>>> d_int
defaultdict(<type 'int'>, {'a': 10, 'c': 13, 'b': 12})
작동 원리
표준 사전의 하위 클래스와 마찬가지로 동일한 기능을 모두 수행 할 수 있습니다.
그러나 알 수없는 키를 전달하면 오류 대신 기본값을 반환합니다. 예를 들어 :
>>> d_int['a']
10
>>> d_int['d']
0
>>> d_int
defaultdict(<type 'int'>, {'a': 10, 'c': 13, 'b': 12, 'd': 0})
기본값을 변경하려면 default_factory를 덮어 씁니다.
>>> d_int.default_factory = lambda: 1
>>> d_int['e']
1
>>> d_int
defaultdict(<function <lambda> at 0x7f34a0a91578>, {'a': 10, 'c': 13, 'b': 12, 'e': 1, 'd': 0})
또는
>>> def foo():
... return 2
>>> d_int.default_factory = foo
>>> d_int['f']
2
>>> d_int
defaultdict(<function foo at 0x7f34a0a0a140>, {'a': 10, 'c': 13, 'b': 12, 'e': 1, 'd': 0, 'f': 2})
문제의 예
실시 예 1
int가 default_factory로 전달되었으므로 알 수없는 키는 기본적으로 0을 반환합니다.
이제 문자열이 루프에 전달되면 d에서 해당 알파벳의 수가 증가합니다.
>>> s = 'mississippi'
>>> d = defaultdict(int)
>>> d.default_factory
<type 'int'>
>>> for k in s:
... d[k] += 1
>>> d.items()
[('i', 4), ('p', 2), ('s', 4), ('m', 1)]
>>> d
defaultdict(<type 'int'>, {'i': 4, 'p': 2, 's': 4, 'm': 1})
실시 예 2
목록이 default_factory로 전달되었으므로 알 수없는 (존재하지 않은) 키는 기본적으로 [] (즉, 목록)을 반환합니다.
이제 튜플 목록이 루프에 전달되면 d [color]에 값이 추가됩니다.
>>> s = [('yellow', 1), ('blue', 2), ('yellow', 3), ('blue', 4), ('red', 1)]
>>> d = defaultdict(list)
>>> d.default_factory
<type 'list'>
>>> for k, v in s:
... d[k].append(v)
>>> d.items()
[('blue', [2, 4]), ('red', [1]), ('yellow', [1, 3])]
>>> d
defaultdict(<type 'list'>, {'blue': [2, 4], 'red': [1], 'yellow': [1, 3]})
여기에 defaultdicts에 대한 훌륭한 설명이 있습니다 : http://ludovf.net/blog/python-collections-defaultdict/
기본적으로 매개 변수 int 및 list 는 전달하는 함수입니다. 파이썬은 함수 이름을 인수로 받아들입니다. int 는 기본적으로 0을 반환하고 괄호와 함께 호출하면 list 는 빈 목록을 반환합니다.
일반적인 사전에서 귀하의 예제 d[a]
에서을 호출하려고 하면 키 m, s, i 및 p 만 존재하고 키 a가 초기화되지 않았기 때문에 오류 (KeyError)가 발생합니다. 그러나 기본적으로 함수 이름을 인수로 사용합니다. 초기화되지 않은 키를 사용하려고하면 전달 된 함수를 호출하고 반환 값을 새 키의 값으로 지정합니다.
사전은 이름 (키)별로 나중에 검색 할 수 있도록 데이터를 저장하는 편리한 방법입니다. 키는 고유하고 변경 불가능한 객체 여야하며 일반적으로 문자열입니다. 사전의 값은 무엇이든 가능합니다. 많은 응용 프로그램에서 값은 정수 및 문자열과 같은 간단한 유형입니다.
사전의 값이 콜렉션 (목록, 딕트 등) 인 경우 더 흥미로워집니다.이 경우 지정된 키를 처음 사용할 때 값 (빈 목록 또는 dict)을 초기화해야합니다. 이 작업은 수동으로 수행하기가 비교적 쉽지만 defaultdict 유형은 이러한 종류의 작업을 자동화하고 단순화합니다. defaultdict는 일반 dict과 똑같이 작동하지만 인수를 사용하지 않고 존재하지 않는 키의 기본값을 제공하는 함수 ( "default factory")로 초기화됩니다.
defaultdict는 절대 KeyError를 발생시키지 않습니다. 존재하지 않는 키는 기본 팩토리에서 리턴 한 값을 가져옵니다.
from collections import defaultdict
ice_cream = defaultdict(lambda: 'Vanilla')
ice_cream['Sarah'] = 'Chunky Monkey'
ice_cream['Abdul'] = 'Butter Pecan'
print(ice_cream['Sarah'])
>>>Chunky Monkey
print(ice_cream['Joe'])
>>>Vanilla
defaultdict를 사용하는 방법에 대한 또 다른 예는 복잡성을 줄일 수 있습니다.
from collections import defaultdict
# Time complexity O(n^2)
def delete_nth_naive(array, n):
ans = []
for num in array:
if ans.count(num) < n:
ans.append(num)
return ans
# Time Complexity O(n), using hash tables.
def delete_nth(array,n):
result = []
counts = defaultdict(int)
for i in array:
if counts[i] < n:
result.append(i)
counts[i] += 1
return result
x = [1,2,3,1,2,1,2,3]
print(delete_nth(x, n=2))
print(delete_nth_naive(x, n=2))
결론적으로, 사전이 필요하고 각 요소의 값이 기본값으로 시작해야 할 때마다 defaultdict를 사용하십시오.
문제는 "작동 방식"에 관한 것이므로 일부 독자는 더 많은 볼트와 너트를보고 싶어 할 것입니다. 구체적으로, 문제의 __missing__(key)
방법 은 방법이다. https://docs.python.org/2/library/collections.html#defaultdict-objects를 참조 하십시오 .
보다 구체적으로,이 답변은 __missing__(key)
실용적인 방법으로 활용하는 방법을 보여줍니다 : https://stackoverflow.com/a/17956989/1593924
'호출 가능'의 의미를 명확히하기 위해 대화식 세션이 있습니다 (2.7.6부터 v3에서도 작동해야 함).
>>> x = int
>>> x
<type 'int'>
>>> y = int(5)
>>> y
5
>>> z = x(5)
>>> z
5
>>> from collections import defaultdict
>>> dd = defaultdict(int)
>>> dd
defaultdict(<type 'int'>, {})
>>> dd = defaultdict(x)
>>> dd
defaultdict(<type 'int'>, {})
>>> dd['a']
0
>>> dd
defaultdict(<type 'int'>, {'a': 0})
이것이 가장 일반적인 defaultdict 사용이었습니다 (x 변수의 무의미한 사용 제외). 명시 적 기본값과 0으로 동일한 작업을 수행 할 수 있지만 간단한 값으로는 수행 할 수 없습니다.
>>> dd2 = defaultdict(0)
Traceback (most recent call last):
File "<pyshell#7>", line 1, in <module>
dd2 = defaultdict(0)
TypeError: first argument must be callable
대신 다음은 간단한 함수를 전달하기 때문에 작동합니다 (인수를 사용하지 않고 항상 0을 반환하는 이름없는 함수를 즉시 생성합니다).
>>> dd2 = defaultdict(lambda: 0)
>>> dd2
defaultdict(<function <lambda> at 0x02C4C130>, {})
>>> dd2['a']
0
>>> dd2
defaultdict(<function <lambda> at 0x02C4C130>, {'a': 0})
>>>
그리고 다른 기본값으로 :
>>> dd3 = defaultdict(lambda: 1)
>>> dd3
defaultdict(<function <lambda> at 0x02C4C170>, {})
>>> dd3['a']
1
>>> dd3
defaultdict(<function <lambda> at 0x02C4C170>, {'a': 1})
>>>
내 자신의 2 ¢ : 당신은 또한 defaultdict를 서브 클래스 화 할 수 있습니다 :
class MyDict(defaultdict):
def __missing__(self, key):
value = [None, None]
self[key] = value
return value
이것은 매우 복잡한 경우에 유용 할 수 있습니다.
defaultdict 도구는 Python의 collections 클래스에있는 컨테이너입니다. 일반적인 사전 (dict) 컨테이너와 유사하지만 한 가지 차이점이 있습니다. 값 필드의 데이터 유형은 초기화시 지정됩니다.
예를 들면 다음과 같습니다.
from collections import defaultdict
d = defaultdict(list)
d['python'].append("awesome")
d['something-else'].append("not relevant")
d['python'].append("language")
for i in d.items():
print i
인쇄합니다 :
('python', ['awesome', 'language'])
('something-else', ['not relevant'])
스위치 케이스 문 대신 가장 잘 사용되는 것 같습니다. 아래와 같이 switch case 문이 있다고 상상해보십시오.
option = 1
switch(option) {
case 1: print '1st option'
case 2: print '2nd option'
case 3: print '3rd option'
default: return 'No such option'
}
switch
파이썬에는 사용 가능한 사례 가 없습니다 . 를 사용하여 동일한 결과를 얻을 수 있습니다 defaultdict
.
from collections import defaultdict
def default_value(): return "Default Value"
dd = defaultdict(default_value)
dd[1] = '1st option'
dd[2] = '2nd option'
dd[3] = '3rd option'
print(dd[4])
print(dd[5])
print(dd[3])
다음을 인쇄합니다.
Default Value
Default Value
3rd option
위의 스 니펫 dd
에는 키 4 또는 5가 없으므로 도우미 기능에서 구성한 기본값을 인쇄합니다. 이것은 KeyError
키가 없으면 a 가 던져지는 원시 사전보다 훨씬 좋습니다 . 이것으로부터 defaultdict
복잡한 if-elif-elif-else
블록을 피할 수있는 스위치 케이스 문장과 비슷 하다는 것이 분명합니다 .
이 사이트 에서 많은 감동을 얻은 또 다른 좋은 예 는 다음과 같습니다.
>>> from collections import defaultdict
>>> food_list = 'spam spam spam spam spam spam eggs spam'.split()
>>> food_count = defaultdict(int) # default value of int is 0
>>> for food in food_list:
... food_count[food] += 1 # increment element's value by 1
...
defaultdict(<type 'int'>, {'eggs': 1, 'spam': 7})
>>>
우리는 이외의 다른 항목에 액세스하려고하면 eggs
그리고 spam
우리는 0의 수를 얻을 것이다.
이 없으면 defaultdict
보이지 않는 키에 새 값을 할당 할 수 있지만 수정할 수는 없습니다. 예를 들면 다음과 같습니다.
import collections
d = collections.defaultdict(int)
for i in range(10):
d[i] += i
print(d)
# Output: defaultdict(<class 'int'>, {0: 0, 1: 1, 2: 2, 3: 3, 4: 4, 5: 5, 6: 6, 7: 7, 8: 8, 9: 9})
import collections
d = {}
for i in range(10):
d[i] += i
print(d)
# Output: Traceback (most recent call last): File "python", line 4, in <module> KeyError: 0
다음과 같은 경우에도 defaultdict에서 키 오류가 발생할 수 있습니다.
from collections import defaultdict
d = defaultdict()
print(d[3]) #raises keyerror
항상 defaultdict (int)와 같은 defaultdict에 인수를 제공해야합니다.
모든 통화 대신 defaultdict
사용하여 행동을 쉽게 모방 할 수 있습니다 .dict.setdefault
d[key]
다시 말해, 코드는 :
from collections import defaultdict
d = defaultdict(list)
print(d['key']) # empty list []
d['key'].append(1) # adding constant 1 to the list
print(d['key']) # list containing the constant [1]
다음과 같습니다.
d = dict()
print(d.setdefault('key', list())) # empty list []
d.setdefault('key', list()).append(1) # adding constant 1 to the list
print(d.setdefault('key', list())) # list containing the constant [1]
유일한 차이점은을 사용 defaultdict
하여 목록 생성자가 한 번만 호출 dict.setdefault
되고 목록 생성자를 사용 하는 것이 더 자주 호출된다는 점입니다 (그러나 실제로 필요한 경우이를 피하기 위해 코드를 다시 작성할 수 있음).
일부는 성능 고려 사항이있을 수 있지만이 주제는 지뢰밭입니다. 이 게시물은 예를 들어 defaultdict를 사용하면 성능이 크게 향상되지 않음을 보여줍니다.
IMO, defaultdict는 코드의 이점보다 혼란을 더하는 모음입니다. 나에게는 쓸모가 없지만 다른 사람들은 다르게 생각할 수 있습니다.
한마디로 :
defaultdict(int)
-int 인수는 값이 int 유형임을 나타냅니다.
defaultdict(list)
-인수 목록은 값이 목록 유형임을 나타냅니다.
표준 사전에는 값을 검색하고 값이없는 경우 기본값을 설정하기위한 setdefault () 메소드가 포함되어 있습니다. 반대로 defaultdict를 사용하면 컨테이너가 초기화 될 때 호출자가 기본값을 미리 지정할 수 있습니다.
import collections
def default_factory():
return 'default value'
d = collections.defaultdict(default_factory, foo='bar')
print 'd:', d
print 'foo =>', d['foo']
print 'bar =>', d['bar']
이것은 모든 키가 동일한 기본값을 갖는 것이 적절하다면 잘 작동합니다. 기본값이 목록, 집합 또는 int와 같은 값을 집계하거나 누적하는 데 사용되는 유형 인 경우 특히 유용합니다. 표준 라이브러리 문서에는 이러한 방식으로 defaultdict를 사용하는 몇 가지 예가 포함되어 있습니다.
$ python collections_defaultdict.py
d: defaultdict(<function default_factory at 0x100468c80>, {'foo': 'bar'})
foo => bar
bar => default value
문서와 설명은 거의 자명하다 :
http://docs.python.org/library/collections.html#collections.defaultdict
인수로 전달 된 type 함수 (int / str 등)는 dict에 키가없는 특정 키의 기본값을 초기화하는 데 사용됩니다.
참고 URL : https://stackoverflow.com/questions/5900578/how-does-collections-defaultdict-work
도와주세요.
'development' 카테고리의 다른 글
파이썬 객체를 올바르게 정리하려면 어떻게합니까? (0) | 2020.02.18 |
---|---|
파이썬에서 인식하지 못하는 날짜 시간 시간대를 인식시키는 방법 (0) | 2020.02.18 |
우분투에서 ssh-add로 개인 키를 영구적으로 추가하는 방법은 무엇입니까? (0) | 2020.02.18 |
여러 인수에 대한 Python 다중 처리 pool.map (0) | 2020.02.18 |
C #에서 예외를 다시 발생시키는 올바른 방법은 무엇입니까? (0) | 2020.02.18 |