__ missing__을 사용해 키에 따라 다른 디폴트 값을 생성하는 방법을 알아두라

매일 공부(ML)·2022년 6월 8일
0

이어드림

목록 보기
70/146

Setdefault or defaultdict를 모두 사용하기 적당하지 않은 경우

예시: 파일 시스템에있는 SNS프로필 사진 관리 프로그램

#필요할 때 읽고 쓰는 프로필 사진의 경로와 열린 파일 핸들을 연관시켜주는 딕셔너리 필요

##get사용

picture {}
path = 'profile_1234.png'

if (handle := pictures.get(path)) is None:
	try:
    	handle = open(path, 'a+b')
    except OSError:
    	print(f'경로를 열 수 없습니다.: {path}')
        raise
    else:
    	pictures[path] = handle
handle.seek(0)
image_data = handle.read()
  • 위와 같은 방식
    • 파일핸들이 딕셔너리 안에 있으면 한 번만 읽는다.
    • 없다면 get을 사용하여 딕셔너리 한 번 읽고 try/except블록의 else절에서 핸들 딕셔너리 대입
    • 단점
      • 딕셔너리를 더 많이 읽게 됨
      • 내포되는 블록 깊이가 더 깊어진다.

#setdefault를  활용하는 게 더 좋다고 생각할 수 있음
try:
	handle =pictures.setdefault(path, open(path, 'a+b'))
except OSError:
	print(f'경로를 열 수 없습니다: {path}')
    raise
else:
	handle.seek(0)
    image_data = handle.read()
  • 위와 같은 방식

    • 단점
      - 코드 문제가 많다.
      - open의 딕셔너리 경로 여부와 상관없이 항상 호출
      - 예외 구분을 하지 못한다.
      ``` #도우미 함수와 defailtdict를 활용해보자

from collections import defaultdict

def open_picture(profile_path):
try:
return open(profile_path, 'a+b')
except OSError:
print(f'경로를 열 수 없습니다: {profile_path}')
raise
picture =defaultdict(open_picture)
handle =pictures[path]
handle.seek(0)

image_data = handle.read()

![](https://velog.velcdn.com/images/qsdcfd/post/34f8ac53-93be-4f7b-a70f-2ee76c8767c2/image.png)

- 위와 같은 방식

    - 단점
    
        - defaultdict생성자에서 전달한 함수는 인자 못 받음
        - 파일경로를 사용해서 open호출 불가
        
 <br>
 
 **파이썬이 제공하는 해결책**
 
 - dict타입의 하위 클래스를 만들고 __missing__ 특별 메서드 구현
 
 - 키가 없는 경우를 처리하는 로직을 커스텀화한다.
 
 

class Pictures(dict):
def missing(self,key):
value = open_picture(key)
self[key] = value
return value
pictures =Pictures()
handle = pictures[path]
handle.seek(0)
image_data = handle.read()


- 
profile
성장을 도울 아카이빙 블로그

0개의 댓글