오늘 정리할 내용은 python에서 제공하는 collections module이다. 널리 알려져서 사용되는 module은 아니지만 그 기능들 중에 유용한 것들이 있어서 counter, namedtuple, defaultdict 정도만 정리를 해보려고 한다.
counter
iterable object에서의 개수 세기
counter는 iterable 객체에서 개수를 세는 계수기(counter)를 위한 class이다.
예를 들어서 list에서 각 element의 개수를 세고 싶다고 해보자.
from collections import Counter
import random
lst = [random.randint(1, 3) for i in range(10)]
print(lst)
[1, 2, 3, 2, 1, 2, 1, 2, 1, 3]
collections 모듈에서 Counter class를 import 하고, random을 이용해서 list를 하나 만들었다.
1에서 3까지의 숫자를 랜덤으로 10개 생성한 list이다.
이때 각 원소의 개수를 세고 싶다면 어떤 코드를 사용할 수 있을까?
글쎄 .. 일단 set을 통해서 unique 하게 만들어 준 다음, 해당하는 원소의 개수를 세지 않을까?
unique_lst = list(set(lst))
{key: lst.count(key) for key in unique_lst}
{1: 4, 2: 4, 3: 2}
unique_lst를 만들어준 다음, dictionary comprehension을 이용해서 개수를 셀 수 있다.
(막상 해보니까 간단해서 놀람 ..)
하지만 counter를 이용하면 아주 조금 더 간단하게 할 수 있다.
c = Counter(lst)
print(c)
print(dict(c))
print(list(c))
Counter({1: 4, 2: 4, 3: 2})
{1: 4, 2: 4, 3: 2}
[1, 2, 3]
앞서 만든 lst를 가지고 Counter object를 만들어준다.
Counter object를 dict 함수 안에 넣어주면 dictionary 형태로 개수를 센 결과를 갖게 되고, list에 담게 되면 유니크한 원소들을 취할 수 있게 된다.
보통 일반적으로 unique 한 list로 만들 때, set으로 감싸고 list로 다시 감싸는데, counter를 이용해도 좋을 것 같다.
string에서의 활용
다음은 string에서 counter를 사용해보려고 한다.
sentences = "Hello Hello this is python blog welcome to python world. python is so funny"
c = Counter(sentences.split())
print(c)
print()
# most common
print(c.most_common())
print()
print(dict(c))
print()
print(list(c))
print()
Counter({'python': 3, 'Hello': 2, 'is': 2, 'this': 1, 'blog': 1, 'welcome': 1, 'to': 1, 'world.': 1, 'so': 1, 'funny': 1})
[('python', 3), ('Hello', 2), ('is', 2), ('this', 1), ('blog', 1), ('welcome', 1), ('to', 1), ('world.', 1), ('so', 1), ('funny', 1)]
{'Hello': 2, 'this': 1, 'is': 2, 'python': 3, 'blog': 1, 'welcome': 1, 'to': 1, 'world.': 1, 'so': 1, 'funny': 1}
['Hello', 'this', 'is', 'python', 'blog', 'welcome', 'to', 'world.', 'so', 'funny']
string에서 split() method를 사용하면 공백을 기준으로 문자열을 분리하게 되고, most_common()을 하게 되면 높은 빈도 순으로 정렬된 tuple을 원소로 하는 list를 얻는다.
dict, list 형태는 위의 list 형태와 같다.
namedtuple
namedtuple은 이름 그대로 이름이 있는 tuple이다.
호출하는 방법은 간단하다.
from collections import namedtuple
일반적으로 tuple에 접근을 할 수는 있지만 이름을 부여할 수는 없다.
예를 들어서 일반적인 tuple의 사용법은 다음과 같다.
t = (10, 20, 30)
print(t[1])
print()
20
이제 namedtuple을 어떻게 사용할 수 있는지 알아보자.
우선 이름을 정의하는 namedtuple 객체를 하나 미리 만들어야 한다.
Car = namedtuple('Car', ['brand', 'color', 'model'])
print(Car)
<class '__main__.Car'>
이제 Car라는 변수를 가지고 namedtuple인 Car라는 object를 만들어보자.
my_car = Car(brand='Hyundai', color="White", model='Sonata')
print(my_car)
print(my_car.brand)
print(my_car[1])
Car(brand='Hyundai', color='White', model='Sonata')
Hyundai
White
그러면 my_car라는 변수에서 이름으로 attribute에 접근이 가능하다. 물론 숫자 인덱스로도 가능하다.
정리하고 보니, namedtuple은 "attribute를 갖는 class를 간편하게 만들 수 있도록 해주는 기능" 정도로 정리하면 좋을 것 같다.
defaultdict
defaultdict는 dictionary에서 없는 key에 대해서 error를 발생시키지 않도록 해주는 module이다. 일반적으로 아래와 같이 없는 key에 대해서 dictionary에 접근을 시도하면 KeyError가 발생한다.
sample_dict = {'x': 10}
print(sample_dict['y'])
384 sample_dict = {'x': 10}
----> 385 print(sample_dict['y'])
KeyError: 'y'
하지만 defaultdict를 사용하면, default 값을 부여하고 KeyError를 발생시키지 않을 수 있다.
# defaultdict never raises a KeyError
from collections import defaultdict
sample_dict_with_default = defaultdict(lambda: 1)
sample_dict_with_default['x'] = 10
print(sample_dict_with_default['here'])
1
호출은 from collections import defaultdict, 그리고 lambda를 통해서 default 값을 부여할 수 있다.
위의 출력 결과를 보면, 없는 key 값에 대해서 lambda로 부여한 1이 출력되었음을 알 수 있다.
이렇게 collections module까지 정리 끝 .. !!
'Pyhon 기초, 실전' 카테고리의 다른 글
[Python 기초] Generator의 뜻과 사용 예시 (0) | 2023.07.22 |
---|---|
[Python 기초] lambda, filter function: 아는 사람만 쓰는 함수 (0) | 2023.07.22 |
[Python 기초] map: 아는 사람만 쓰는 built-in function (0) | 2023.07.19 |
[Python 기초] 날짜 및 시간 다루기: datetime module 소개 (0) | 2023.07.18 |
[Python 기초] list, dictionary comprehension and conditional comprehension (1) | 2023.07.17 |