
None 반환
- 의미 있는 None 반환보다 예외를 raise 시키자.
def divide(a, b):
try:
return a / b
except ZeroDivisionError as e:
raise ValueError('Invalid inputs') from e
클로저
def sort_prioriy(numbers, group):
found = False
def helper(x):
if x in group:
found = True
return (0, x)
return (1, x)
numbers.sort(key=helper)
return found
numbers.sort(key=helper) found의 값이 변해도 sort_prioriy() 에서는 found값이 바뀌지 않는다.
numbers.sort(key=helper) 에서 helper는 sort_prioriy() 의 스코프에 해당하는 변수들을 copy 해서 사용한다고 생각하면 편하다. 복사본의 값을 변경해도 원본의 값이 변하지 않는 것처럼 말이다.
def sort_prioriy(numbers, group):
found = False
def helper(x):
nonlocal found
if x in group:
found = True
return (0, x)
return (1, x)
numbers.sort(key=helper)
return found
nonlocal 문을 사용하여 클로저를 감싸는 있는 스코프의 변수를 수정할 수 있다.
- 간단한 함수에만 사용하자.
제네레이터
def index_words(txt):
result = []
if txt:
result.append(0)
for index, letter in enumerate(txt):
if letter = ' ':
result.append(index + 1)
return result
def index_words_iter(txt):
if test:
yield 0
for index, letter in enumerate(txt):
if letter == ' ':
yield index + 1
result = list(index_words_iter(address))
- 제네레이터는 이터레이터를 반환한다
- 리스트를 반환할 때는 제네레이터를 고려하자
인수 순회 방어적으로 하기
def normalize(numbers: list):
total = sum(numbers)
for num in numbers:
yield 100 * num / total
result = normalize([15, 35, 80])
print(list(result))
print(list(result))
- 제네레이터는 StopIteration 예외가 일어나면 결과 값을 저장하지 않는다.
즉, 이터레이터로 결과를 한 번만 생성한다.
class Normalize:
def __init__(self, numbers):
self.numbers = numbers
def __iter__(self):
total = sum(self.numbers)
for num in self.numbers:
yield 100 * num / total
result = normalize([15, 35, 80])
print(list(result))
print(list(result))
- 이터레이터를 독립적으로 실행하면 입력 데이터를 여러번 읽는 단점만 빼면 기댓값을 얻을 수 있다.
가변 위치 인수
def log(message, *values):
if not values:
print(message)
else:
values_str = ', '.join(str(x) for x in values)
print(f'{message} : {values_str}')
numbers = [21, 33, 31]
log("Hi")
log("My numbers are", 1, 2, 3)
log("My favorite numbers are", *numbers)
- 깔끔한 코드를 작성할 수 있다.
- 가변 위치 변수는 함수로 전달되기에 앞서 튜플로 변환된다.
- 호출 코드 수정 하기 전에는 위치 인수를 추가할 수 없다.
기본 인수를 None과 docstring 활용하기
키워드 전용 인수
def division(number, divisor, *,
ignore_overview=False,
ignore_zero_division=False)
division(1, 10**500, True, False)
division(1, 0, ignore_zero_division=True)