def careful_divide(a, b):
try:
return a / b
except ZeroDivisionError:
return None
#
x, y = 1, 0
result = careful_divide(x, y)
if result is None:
print('잘못된 입력')
#
x, y = 0, 5
result = careful_divide(x, y)
if not result:
print('잘못된 입력') # 이 코드가 실행되는데, 사실 이 코드가 실행되면 안된다!
def careful_divide(a: float, b: float) -> float:
"""a를 b로 나눈다.
Raises:
ValueError: b가 0이어서 나눗셈을 할 수 없을 때
"""
try:
return a / b
except ZeroDivisionError as e:
raise ValueError('잘못된 입력')
try:
result = careful_divide(x, y)
except ValueError:
print('잘못된 입력')
else:
print('결과는 %.1f 입니다' % result)
sort
메서드는 helper 함수를 key 인자로 받을 수 있다.def sort_priority(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 = [8, 3, 1, 2, 5, 4, 7, 6]
group = {2, 3, 5, 7}
found = sort_priority(numbers, group)
print('발견:', found)
print(numbers)
식 안에서 변수를 참조할 때,
식 안에서 변수에 값을 대입할 때,
#
def sort_priority(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
class Sorter:
def __init__(self, group):
self.group = group
self.found = False
def __call__(self, x):
if x in self.group:
self.found = True
return (0, x)
return (1, x)
numbers = [8, 3, 1, 2, 5, 4, 7, 6]
group = {2, 3, 5, 7}
sorter = Sorter(group)
numbers.sort(key=sorter)
assert sorter.found is True
*
연산자는 파이썬이 sequence의 원소들을 -> 함수의 위치 인자로 넘길 것을 명령한다. def log(message, *values):
if not values:
print(message)
else:
values_str = ', '.join(str(x) for x in values)
print(f'{message}: {values_str}')
log('내 숫자는 ', [1, 2])
log('안녕 ') # 안써도 되어서, 훨씬 좋다
## 중요. * 용법이 특이하다.
favorites = [7, 33, 99]
log('좋아하는 숫자는', *favorites)
def my_generator():
for i in range(10):
yield i
def my_func(*args):
print(args)
it = my_generator()
my_func(*it)
>>>
(0, 1, 2, 3, 4, 5, 6, 7, 8, 9)
keyword argument의 장점
선택적인(가변적인) argument를 지정하는 최선의 방법은, 항상 keyword arguemnt를 사용하고 positional argument를 절대 사용하지 않는 것이다.
특징
사용법
def remainder(number, divisor):
return number % divisor
my_kwargs = {
'number': 20,
'divisor': 7,
}
assert remainder(**my_kwargs) == 6
# case 1
my_kwargs = {
'divisor': 7,
}
assert remainder(number=20, **my_kwargs) == 6
# case 2
my_kwargs = {
'number': 20,
}
other_kwargs = {
'divisor': 7,
}
assert remainder(**my_kwargs, **other_kwargs) == 6
**kwargs
파라미터를 사용한다.def print_parameters(**kwargs):
for key, value in kwargs.items():
print(f'{key} = {value}')
print_parameters(alpha=1.5, beta=9, 감마=4)
def log(message, when=datetime.now()):
print(f'{when}: {message}')
def log(message, when=None):
"""메시지와 타임스탬프를 로그에 남긴다.
Args:
message: 출력할 메시지.
when: 메시지가 발생한 시각(datetime).
디폴트 값은 현재 시간이다.
"""
if when is None:
when = datetime.now()
print(f'{when}: {message}')
log('안녕!')
sleep(0.1)
log('다시 안녕!')
from typing import Optional
from datetime import datetime
def log_typed(message: str,
when: Optional[datetime]=None) -> None:
"""메시지와 타임스탬프를 로그에 남긴다.
Args:
message: 출력할 메시지.
when: 메시지가 발생한 시각(datetime).
디폴트 값은 현재 시간이다.
"""
if when is None:
when = datetime.now()
print(f'{when}: {message}')
def safe_division_e(numerator, denominator, /,
ndigits=10, *, # 변경
ignore_overflow=False,
ignore_zero_division=False):
try:
fraction = numerator / denominator # 변경
return round(fraction, ndigits) # 변경
except OverflowError:
if ignore_overflow:
return 0
else:
raise
except ZeroDivisionError:
if ignore_zero_division:
return float('inf')
else:
raise
/
이전에 온 arguments은, position으로만 지정해야 하는 argument 이다. (keyword 로 호출하면 에러가 난다.)*
다음에 온 arguments는, keyword로만 지정해야 하는 argument 이다. (position으로 호출하면 에러가 난다.)/
와 *
사이에 있는 파라미터는, 키워드를 사용해 전달해도 되고, 위치를 기반으로 전달해도 된다. (이런 동작은 python 함수 파라미터의 기본 동작이다.)@
기호를 사용하는 것은,wrapper = trace(fibonacci)
wrapper
)from functools import wraps
def trace(func):
@wraps(func)
def wrapper(*args, **kwargs):
result = func(*args, **kwargs)
print(f'{func.__name__}({args!r}, {kwargs!r}) '
f'-> {result!r}')
return result
return wrapper
@trace
def fibonacci(n):
"""Return n 번째 피보나치 수"""
if n in (0, 1):
return n
return (fibonacci(n - 2) + fibonacci(n - 1))
fibonacci(4)
print(fibonacci)
wraps
를 wrapper 함수에 적용하면, wraps
가 decorator 내부에 들어가는 함수에서 중요한 metadata를 복사해, wrapper 함수에 적용해준다.