키워드 인자의 유연성을 활용하면 여러분의 코드를 처음 읽는 사람도 더 명확하게 용례를 이해할 수 있는 함수를 작성할 수 있다.
def safe_division(number, divisor,
ignore_overflow,
ignore_zero_divison):
try:
return number / divisor
except OverflowError:
if ignore_overflow:
return 0
else:
raise
except ZeroDivisionError:
if ignore_zero_divison:
return float('inf')
else:
raise
safe_division(1.0, 10**500, True, False)
0
1.0 / 10**500
--------------------------------------------------------------------------- OverflowError Traceback (most recent call last) <ipython-input-11-937ebf0ae6da> in <module> ----> 1 1.0 / 10**500 OverflowError: int too large to convert to float
safe_division(1.0, 0, False, True)
inf
문제는 어떤 예외를 무시할지 결정하는 두 불 변수의 위치를 혼동하기 쉽다는 것이다.
def safe_division(number, divisor,
ignore_overflow=False,
ignore_zero_divison=False):
try:
return number / divisor
except OverflowError:
if ignore_overflow:
return 0
else:
raise
except ZeroDivisionError:
if ignore_zero_divison:
return float('inf')
else:
raise
safe_division(1.0, 10**500)
--------------------------------------------------------------------------- OverflowError Traceback (most recent call last) <ipython-input-14-4fb969c7fd48> in <module> ----> 1 safe_division(1.0, 10**500) <ipython-input-13-35495800f432> in safe_division(number, divisor, ignore_overflow, ignore_zero_divison) 3 ignore_zero_divison=False): 4 try: ----> 5 return number / divisor 6 except OverflowError: 7 if ignore_overflow: OverflowError: int too large to convert to float
safe_division(1.0, 10**500, ignore_overflow=True)
0
safe_division(1.0, 0, ignore_zero_divison=True)
inf
그러나 키워드 인자를 강요할 수 없다.
이와 같이 복잡한 함수의 경우 호출자가 키워드만 사용하는 인자를 통해 의도를 명확히 밝히도록 요구하는 편이 좋다.
절대 위치를 기반으로는 지정할수 없도록 한다.
*****을 사용한다
def safe_division(number, divisor, *,
ignore_overflow=False,
ignore_zero_divison=False):
try:
return number / divisor
except OverflowError:
if ignore_overflow:
return 0
else:
raise
except ZeroDivisionError:
if ignore_zero_divison:
return float('inf')
else:
raise
safe_division(1.0, 10**500, True, False)
--------------------------------------------------------------------------- TypeError Traceback (most recent call last) <ipython-input-19-bfb72866806f> in <module> ----> 1 safe_division(1.0, 10**500, True, False) TypeError: safe_division() takes 2 positional arguments but 4 were given
safe_division(1.0, 10**500, ignore_overflow=True)
0
하지만 키워드 인자와 디폴트 값은 예상대로 잘 작동한다.
safe_division(1.0, 0)
--------------------------------------------------------------------------- ZeroDivisionError Traceback (most recent call last) <ipython-input-21-fec255ac0672> in <module> ----> 1 safe_division(1.0, 0) <ipython-input-17-8d972f3b7033> in safe_division(number, divisor, ignore_overflow, ignore_zero_divison) 3 ignore_zero_divison=False): 4 try: ----> 5 return number / divisor 6 except OverflowError: 7 if ignore_overflow: ZeroDivisionError: float division by zero
하지만 이 함수에도 문제가 있다.
이 함수의 맨 앞에 있는 두 필수 인자 (number, divisor)를 호출하면서 위치와 키워드를 혼용할 수 있다.
safe_division(number=2, divisor=5)
0.4
safe_division(divisor=5, number=2)
0.4
safe_division(2, divisor=5)
0.4
def safe_division_c(numerator, denominator, *,
ignore_overflow=False,
ignore_zero_divison=False):
try:
return number / divisor
except OverflowError:
if ignore_overflow:
return 0
else:
raise
except ZeroDivisionError:
if ignore_zero_divison:
return float('inf')
else:
raise
safe_division_c(number=2, divisor=5)
--------------------------------------------------------------------------- TypeError Traceback (most recent call last) <ipython-input-26-eea3389c34ee> in <module> ----> 1 safe_division_c(number=2, divisor=5) TypeError: safe_division_c() got an unexpected keyword argument 'number'
파이썬 3.8에는 이 문제에 대한 해법이 있다.
위치로만 지정하는 인자 라고 부른다.
/ 을 사용한다
def safe_division_d(numerator, denominator, /, *,
ignore_overflow=False,
ignore_zero_divison=False):
try:
return numerator / denominator
except OverflowError:
if ignore_overflow:
return 0
else:
raise
except ZeroDivisionError:
if ignore_zero_divison:
return float('inf')
else:
raise
safe_division_d(2, 5)
0.4
safe_division_d(numerator=2, denominator=5)
--------------------------------------------------------------------------- TypeError Traceback (most recent call last) <ipython-input-34-ec4fa4b0805d> in <module> ----> 1 safe_division_d(numerator=2, denominator=5) TypeError: safe_division_d() got some positional-only arguments passed as keyword arguments: 'numerator, denominator'
/와 * 기호 사이에 있는 모든 파라미터는 위치를 사용해 전달 할 수도 있고 이름을 키워드로 사용해 전달할 수도 있다.
def safe_division_e(numerator, denominator, /,
ndigits=10, *,
ignore_overflow=False,
ignore_zero_divison=False):
try:
fraction = numerator / denominator
return round(fraction, ndigits)
except OverflowError:
if ignore_overflow:
return 0
else:
raise
except ZeroDivisionError:
if ignore_zero_divison:
return float('inf')
else:
raise
safe_division_e(22, 7)
3.1428571429
safe_division_e(22, 7, 5)
3.14286
safe_division_e(22, 7, ndigits=2)
3.14