[Effective Python] | September 14, 2020
Effective Python: Second Edition 내용 정리
get
Over in
and KeyError
to Handle Missing Dictionary Keysin
expression 이나 KeyError
보다는 get
method를 사용하라.get
보다 setdefault
가 가장 짧은 option처럼 보이는데, 이런 경우에도 setdefault
보다는 defaultdict
(Item 17 참조)가 better option이 되는 경우가 많다.If
statement with an in
expression이 방법은 키값이 있을 때는 two accesses to key, one assignment이고, 키값이 없으면 one access, one assignment 이다.
fruits = {'apple': 2, 'banana': 1}
fruit = 'orange'
# Case 1
if fruit in fruits:
count = fruits[fruit]
else:
count = 0
fruits[fruit] = count + 1
코드를 더 줄일 수 있는 방법도 있지만, assignments에 대해 중복이 생긴다.
# Case 2
if fruit not in fruits:
fruits[fruit] = 0
fruits[fruit] += 1
KeyError
using try-except이 방법은 one access, one assignment 이기 때문에 if … in 보다 더 효율적이다.
fruits = {'apple': 2, 'banana': 1}
fruit = 'orange'
# Case 1
try:
count = fruits[fruit]
except KeyError:
count = 0
fruits[fruit] = count + 1
역시 코드를 더 줄일 수 있는 방법이 있지만, 할당하는 코드의 중복이 생긴다.
# Case 2
try:
fruits[fruit] += 1
except KeyError:
fruits[fruit] = 1
get
method이 방법 역시 one access, one assignment이고, 다른 방법들보다 짧게 코드를 쓸 수 있다.
fruits = {'apple': 2, 'banana': 1}
fruit = 'orange'
count = fruits.get(fruit, 0)
fruits[fruit] = count + 1
위의 예시들처럼 dictionary에 counters를 저장할 때, collections.Counter
를 사용해보자. 대부분의 필요한 기능들을 제공한다.
from collections import Counter
fruits = Counter({'apple': 2, 'banana': 1})
fruits['apple'] += 1
fruits
>>> Counter({'apple': 3, 'banana': 1})
fruits['apple']
>>> 3
values
for keys are list
:Case 1: in expression
fruits = {'apple': ['a1', 'a2'], 'banana': ['b1', 'b2']}
fruit = 'orange'
name = 'o1'
if fruit in fruits:
names = fruits[fruit]
else:
fruits[fruit] = names = []
names.append(name)
Case 2: KeyError exception
try:
names = fruits[fruit]
except KeyError:
fruits[fruit] = names = []
names.append(name)
Case 3: get method
names = fruits.get(fruit)
if names is None:
fruits[fruit] = names = []
names.append(name)
Case 4: get method + assignment expression(walrus operation)
코드가 더 짧고 가독성도 높일 수 있다. (Item 10: Prevent Repetition with Assignment Expressions 참조)
# python 3.8
if (names := fruits.get(fruit)) is None:
fruits[fruit] = names = []
names.append(name)
Case 5: setdefault method
setdefault method는 key의 value 값을 가지고 오며, key가 없으면 두번째 parameter를 value 값으로 할당해준다.
names = fruits.setdefault(fruit, [])
names.append(name)
setdefault
라는 이름이 딱 봤을 때 그 목적이 뭔지 알기 어렵다.
value를 set만 하는 게 아니라 get하는 method이기도 한데, 왜 get_or_set
이라고 하지 않을까?💡 get
은 value 값을 copy 해오고, setdefault
는 value 값을 dict에 직접 접근해서 새로 할당한 것을 가져온다.
missing dictionary keys를 처리할 때, setdefault를 쓰는 게 더 나은 경우는 별로 없다.
예를 들면, setdefault가 할당해야하는 default values가 생성하기에 무겁지 않고, mutable(변경 가능)하며, exception이 생길 가능성이 없을 때.
하지만 이런 경우에 setdefault
대신에 defaultdict
를 사용해야 한다.
(Item 17: Prefer defaultdict Over setdefault to Handle Missing Items in Internal State 참조)