[Python] Skill of coding - keyword args의 동작

Hyeseong·2020년 12월 9일
0

python skill of coding

목록 보기
12/18

키워드 인수로 선택적인 동작을 제공하기

함수를 호출할 시 인수를 위치로 전달 할 수 있다.


def remainder(number, divisor):
    return number % divisor

assert remainder(20, 7) == 6

파이썬 함수의 위치 인수를 모두 키워드로 전달 할 수도 있어요. 이때 인수의 이름을 함수 호출의 괄호 안에 있는 할당문에서 사용해요. 이때 인수의 이름을 함수 호출의 괄호 안에 있는 할당문에서 사용해요. 필요한 위치 인수를 모두 지정한다면 키워드 인수로도 전달할 수 있어요. 키워드 위치 인수를 섞어서 사용할 수 있기도 해요.
아래 호출은 모두 동일해요.

def remainder(number, divisor):
    return number % divisor


remainder(20, 7)
remainder(20, divisor=7)
remainder(number=20, divisor=7)
remainder(divisor=7, number=20)
def remainder(number, divisor):
    return number % divisor

remainder(number=20,7) # 7이 위치 인수 , number=20가 키워드`
  File "<ipython-input-118-cedb2b4106e0>", line 4
    remainder(number=20,7) 
                        ^
SyntaxError: positional argument follows keyword argument

위치 인수는 키워드 인수 앞에 위치해야해요.

remainder(20, number=7)
---------------------------------------------------------------------------
TypeError                                 Traceback (most recent call last)
<ipython-input-116-6163636d1711> in <module>
----> 1 remainder(20, number=7) 

TypeError: remainder() got multiple values for argument 'number'

각 인수는 한번만 지정 할 수 있어요.

키워드 인수의 유연성은 세가지 중요성이 있어요.

하나

처음 보는 사람이 함수 호출을 더 명확하게 이해할 수 있다는 점.
remainer 메서드의 구현을 보지 않고는 어떤 인수가 분자, 분모에 해당 하는 수인지 명확하지 않아요. 그래서 키워드 인자의 이름표를 보고 아~ 이게 그거구나라는 직관적 추측으로 인자의 쓰임을 알 수 있어요.

기본 값을 설정 할 수 있어요. 대부분은 기본값을 사용하지만 필요할 때 부가 기능을 제공할 수 있어요. 이렇게 하면 반복 코드가 줄어들고 코드가 깔끔해져요.

예를 들어 큰통에 들어가는 액체의 유속을 계산하다고 해볼게요. 큰 통의 무게를 잴 수 있다면, 각기 다른 시각에 측정한 두 무게의 차이를 이용해 유속을 알 수 있어요.



def flow_rate(weight_diff, time_diff):
    return weight_diff / time_diff

weight_diff = 0.5
time_diff = 3
flow = flow_rate(weight_diff, time_diff)
print('%.3f kg per second' % flow)
assert (flow - 0.16666666666666666) < 0.0001
0.167 kg per second

보통은 초당 킬로그램 단위로 유속을 아는게 좋아요. 하지만 센서의 최근 측정 값을 이용해 시간이나 날짜처럼 더 큰 시간 단위로 계산하는 게 좋을 때도 있어요. 함수의 인수에 기간 환산 계수를 추가하면 이런 동작을 제공할 수 있어요.


def flow_rate(weight_diff, time_diff, period):
    return (weight_diff / time_diff) * period

문제는 함수 호출 시, 심지어 초당 유속을 사용하는 일반적인 경우(period가 1 )에도 period를 설정해야한다는 점이에요.

flow_per_second = flow_rate(weight_diff, time_diff, 1)
assert (flow_per_second - 0.16666666666666666) < 0.0001

period 인수에 기본값을 설정하면 위의 코드를 좀 더 깔끔하게 만들 수 있어요.

def flow_rate(weight_diff, time_diff, period=1):
    return (weight_diff / time_diff) * period
period가 이제 선택적인 인수가 되었어요.


```python

flow_per_second = flow_rate(weight_diff, time_diff)      # period 인자값 입력없이 초당 계산 가능
assert (flow_per_second - 0.16666666666666666) < 0.0001
flow_per_hour = flow_rate(weight_diff, time_diff, period=3600) # 한 시간 단위
assert flow_per_hour == 600.0

위의 코드는 간단한 기본 값에는 잘 동작해요(기본 값이 복잡할 때는 다루기 까다로워요.)

키워드 인수의

세 번째 이점

기존의 호출 코드와 호환성을 유지하면서도 함수의 파라미터를 확장할 수 있는 강력한 수단이 된다는 점이에요. 이 방법을 쓰면 코드를 많이 수정하지 않고서도 추가적인 기능을 제공 할 수 있고, 버그가 생길 가능성을 줄 일 수 있어요.

예를 들어 킬로그램 단위는 물론 다른 무게 단위로도 유속을 계산하려고 앞의 flow_rate 함수를 확장한다고 하면, 원하는 측정 단위의 변환 비율을 새 선택 파라미터로 추가하여 확장하면 되요.

def flow_rate(weight_diff, time_diff,
              period=1, units_per_kg=1):
    return ((weight_diff * units_per_kg) / time_diff) * period

units_per_kg 인수의 기본값은 1로, 반환되는 무게 단위는 킬로그램이 되요.
즉, 기존 호출 코드의 동작에는 변화가 없어요. flow_rate를 새로 호출하는 코드에서는 새 키워드 인수로 새로운 동작을 지정할 수 있어요.

pounds_per_hour = flow_rate(weight_diff, time_diff, period=3600, units_per_kg=2.2)

이 방법의 유일한 문제는 period와 units_per_kg 같은 선택적인 키워드 인수를 여전히 위치 인수로도 넘길 수 있다는 점이에요.

pounds_per_hour = flow_rate(weight_diff, time_diff, 3600, 2.2)
print(pounds_per_hour)
assert pounds_per_hour == 1320.0
1320.0

선택적인 인수를 위치로 넘기면 3600과 2.2 값에 대응하는 인수가 무엇인지 명확하지 않아 혼동을 일으킬 수 있어요. 가장 좋은 방법은 항상 키워드 이름으로 선택적인 인수를 지정하고 위치 인수로는 아예 넘기지 않는겁니다.

이런 선택적인 키워드 인수를 사용하면 *args를 인수로 받는 함수에서 하위 호환성을 지키기 어려워요. 더 좋은 방법은 키워드 전용인수를 사용하는 거에요.

핵심정리

  • 함수의 인수를 위치나 키워드로 지정
  • 위치 인수만으로는 이해하기 어려울 때 키워드 인수를 쓰면 각 인수를 사용하는 목적이 명확해짐
  • 키워드 인수에 기본값을 지정하면 함수에 새 동작을 쉽게 추가할 수 있다. 특히, 함수를 호출하는 기존 코드가 있을 때 사용하면 좋다.
  • 선택적인 키워드 인수는 항상 위치가 아닌 키워드로 넘김
profile
어제보다 오늘 그리고 오늘 보다 내일...

0개의 댓글