※ 이 내용은 Python(개정 2판)의 코딩 기술을 기반으로 작성되었습니다.
키워드 인수의 값으로 정적으로 결정되지 않은 유형의 값을 작성해야 하는 경우가 종종 있습니다.
예를 들어 아래와 같이 로그 메시지와 시간 출력에 해당합니다.
from time import sleep
from datetime import datetime
def log(message, when=datetime.now()):
print(f'{when}: {message}')
log('하잉')
sleep(0.1)
log('하아아잉')
>>>
2019-07-06 14:06:15.120124: 하잉
2019-07-06 14:06:15.120124: 하아아잉
함수가 호출될 때마다 기본 인수가 다시 계산된다고 가정하면 다음 접근 방식을 사용할 수 있습니다.
그러나 datetime은 함수에서 한 번만 호출되기 때문에 타임스탬프는 항상 호출되었을 때와 동일합니다.
이 경우 원하는 동작을 달성하기 위한 Python의 단방향 규칙은 기본적으로 없음으로 지정하고 독스트링에 실제 동작을 문서화하는 것입니다.
코드의 인수가 없음이면 적절한 기본값을 할당해야 합니다.
def log(message, when=None):
"""Log a message with a timestamp.
Args:
message: Message to print.
when: datetime of when the message occurred.
Defaults to the present time.
"""
if when is None:
when = datetime.now()
print(f'{when}: {message}')
log('Hi there!')
sleep(0.1)
log('Hello again!')
>>>
2019-07-06 14:06:15.222419: Hi there!
2019-07-06 14:06:15.322555: Hello again!
None을 기본 인수 값으로 사용하는 것은 인수가 변수일 때 특히 중요합니다.
JSON 데이터로 인코딩된 값을 읽으려고 하는데 데이터 디코딩이 실패하면 기본적으로 빈 사전을 반환하고 싶습니다.
import json
def decode(data, default={}):
try:
return json.loads(data)
except ValueError:
return default
foo = decode('bad data')
foo('stuff') = 5
bar = decode('also bad')
bar('meep') = 1
print('Foo:', foo)
print('Bar:', bar)
>>>
Foo: {'stuff': 5, 'meep': 1}
Bar: {'stuff': 5, 'meep': 1}
이 문제는 위의 타임스탬프 오류와 유사합니다.
foo와 bar는 모두 같은 사전의 객체이기 때문에 하나의 사전을 변경하면 다른 사전도 변경되는 것처럼 보입니다.
이 문제에 대한 해결책은 None을 키워드 인수의 기본값으로 지정하고 함수의 문서 문자열에서 동작을 설명하는 것입니다.
def decode(data, default=None):
"""Load JSON data from a string.
Args:
data: JSON data to decode.
default: Value to return if decoding fails.
Defaults to an empty dictionary.
"""
try:
return json.loads(data)
except ValueError:
if default is None:
default = {}
return default
foo = decode('bad data')
foo('stuff') = 5
bar = decode('also bad')
bar('meep') = 1
print('Foo:', foo)
print('Bar:', bar)
assert foo is not bar
>>>
Foo: {'stuff': 5}
Bar: {'meep': 1}
- 기본 인수 값은 인수가 포함된 함수 정의가 포함된 모듈이 로드될 때 한 번만 평가됩니다. 이러한 이유로 동적 값({ }, (), datetime.now())은 비정상적인 동작을 유발할 수 있습니다.
- 동적 값을 가질 수 있는 키워드 인수에 대한 기본값을 표현하려면 None을 사용하십시오. 그리고 함수의 docstring에서 실제 기본 동적 인수가 작동하는 방식을 문서화합니다.
- 타입 어노테이션을 사용하는 경우에도 None을 사용하여 키워드 인수의 기본값을 표현할 수 있습니다.
