Python/Python__works

dictionary

말하는감자 2020. 10. 12. 16:56

1딕셔너리에서 원하지 않는 값을 안전하게 지워보자

  • 순회문 도중에 pop 남발하기

    • pop은 정확하게는 지우는 것이 아니라, 지정한 key의 value만(!) 던져주고 딕셔너리에서는 지워버립니다.

test_dict_01 = dict()
test_dict_01['a'] = 1
test_dict_01['b'] = ''
test_dict_01['c'] = None
for k, v in test_dict.items():
    if v == None:
        test_dict.pop(k)

위와 같이 순회문 도중에 pop으로 지우면 갑분 에러를 만나게 됩니다.

Traceback (most recent call last):
  File "test.py", line 6, in <module>
    for k, v in test_dict.items():
RuntimeError: dictionary changed size during iteration    

  • 조용히 pop

만약 pop을 쓰고 싶다면 아래와 같이 순회문을 돌지 않고 단독으로 지워줘야 합니다.

test_dict_01.pop('a')

  • pop을 쓰지 않고 안전하게 원하는 값만 필터링 하고 싶다면 필터링된 새로운 딕셔너리를 생성해주어야 합니다.

new_dict = dict({k: v for k, v in test_dict_01.items() if v != None})
print(new_dict)
'''
{'a': 1, 'b': ''}
'''

문법 공부를 할때 이걸 어따써 왜써 이런 생각을 할때가 있어서 첨언하자면.....

위와 같은 구문을 제가 주로 사용하는 부분은 특정 api에서 값을 받아와서 새로운 딕셔너리를 만들고 db에 insert 해주거나 할때 주로 사용했습니다.

api에서 보통은 일정하게 주지만 간혹 개떡같이 잘못 만들었거나 그 값을 아직 제공할 수 없는 상태일때는 분명 int로 받기로 협의가 되어있음에도 Null 이나 '' 같은걸로 떨어질때도 있습니다. 그때 db의 컬럼이 date라던가....... date라던가...ㅠㅠ date라면 

int() argument must be a string, a bytes-like object or a number, not 'NoneType'

이런 친구가 마구마구 화를 낼 때도 있어요. 그런 값을 필터링 할때 좋은 방법이죠.

더 좋은 방법이 있을지도 모르겠지만 제가 아는것은 여기까지.. 


  • 딕셔너리 기본값 지정해주기 1

from collections import defaultdict
test_dict_02 = defaultdict(int)
print(test_dict_02['test1'])
'''
0
'''

test_dict_03 = defaultdict(str)
print(test_dict_03['test1'])
'''

'''

위와 같이 defaultdict에 기본 형을 잡아주면 딕셔너리에 해당 key가 없더라도 오류가 발생하지 않습니다. 

다만 이런 류의 초기화된 딕셔너리를 실제 업무에서 써본적은 없습니다. 전체 값이 일관적인 일이 없어서 -_-;;


  • 딕셔너리 기본값 지정해주기 2
test_json = [
    {
        "test1": 1,
        "test2": "a",
        "test3": "b"
    },
    {
        "test1": 2,
        "test2": "b",
    }
]
for i in test_json:
    test_dict_04 = dict()
    test_dict_04.setdefault('test1', 0)
    test_dict_04.setdefault('test2', '')
    test_dict_04.setdefault('test3', '')
    try:
        test_dict_04['test1'] = i['test1']
        test_dict_04['test2'] = i['test2']
        test_dict_04['test3'] = i['test3']
    except:
        pass
    print(test_dict_04)

실무적일것 같지 않지만 실제로 종종 마주치는 예제입니다. 

test_json 의 1번 인덱스에 "test3" 키가 없습니다. 좀 짧은 메서드면 키가 없는지 있는지 체크라도 수작업으로(가내수공업) 해보던가 할텐데 key를 몇개나 쓸지 모르는 상황일수도 있죠. 기타등등 기타등등.......

실제로 내가 써야할 test_dict_04에서 중요한 key와 기본값은 미리 잡아줍니다.(이 아이는 null 허용하지 않았어...)


  • key가 있는지 없는지 확인이라도 해보고 값을 가져와보자
test_dict_05 = dict()
test_dict_05['a'] = 1

if 'a' in test_dict_05.keys():
    print(test_dict_05['a'])

  • 딕셔너리를 업데이트해보자

하나씩 추가하려면 그냥 추가해주면 됩니다.

test_dict_06 = dict()
test_dict_06['a'] = 1
test_dict_06['b'] = 2

만약 여러개를 한번에 합치고 싶다면..

test_dict_06 = dict()
test_dict_06 = {
	'a': 1,
    'b':2
}

test_dict_07 = dict()
test_dict_07 = {
	'c': 3,
    'd': 4
}

test_dict_06.update(test_dict_07)

print(test_dict_06)

'''
{'a': 1, 'b': 2, 'c': 3, 'd': 4}
'''

 

추가중..

 

'Python > Python__works' 카테고리의 다른 글

PHPSESSID  (0) 2020.12.27
calendar 를 이용해서 년-월-일 목록 뽑아내기  (0) 2020.11.19
mysqlclient  (0) 2020.09.28
서버의 로그를 파이썬으로 읽어서 slack으로 전달하기  (0) 2020.09.24
datetime 활용하기  (0) 2020.09.24