PYTHONIC 매개변수와 인자는 이렇게 다루라!

Lightman·2021년 7월 1일
4

CS: PYTHON🐍 & Ⓡ

목록 보기
10/14
post-thumbnail

40분 작성한 글이 날아갔습니다. 임시저장 되는 중 아니었? 아니었어요? 아니었? 어요? ㅎ


Effective Python 2nd 이펙티브 파이썬 : 파이썬 코딩의 기술의 BETTERWAY22,23,24,25의 내용입니다.


📕 함수와 매개변수 & 함수의 호출과 인자

함수매개변수를 갖고 정의됩니다.

def func( arg1, arg2 = True, *args, **kwargs ) : ...

함수를 호출할 때 호출자caller는 인자를 함수에 전달합니다. 인자를 전달하는 방법에는 위치 인자키워드 인자가 있습니다.

my_list = [1, 2, 3]
my_dict = {'first' = 1, 'second' = 2}
func( 1, arg2 = False, *my_list, **my_dict )

함수가 매개변수를 어떻게 설정하느냐에 따라 인자를 사용하는 방식이 달라집니다. 함수는 보통의 위치 인자키워드 인자를 받을 수도 있고, 선택적인 인자를 받을수도 있으며, 가변적인 동시에 선택적인 위치 인자와 키워드 인자를 받을 수도 있습니다. 그리고 디폴트 값을 가진 매개변수에 None을 적용하면 동적으로 변수를 할당할 수도 있습니다.

🛴 매개변수와 인자의 구분

다음을 염두에 두고 표를 살펴봅시다.

  1. 일반적인 (불변 인자를 받는) 매개변수
    1.1. 디폴트 값을 가진 매개변수
  2. 가변 인자를 받을 수 있는 매개변수: *args, **kwargs
  3. 기타
    3.1. 위치 인자와 키워드 인자의 명시적 구분: /, *
    3.2. 디폴트 값을 가진 매개변수의 동적 할당: None

1. 일반적인 (불변인자를 받는) 매개변수

함수는 일반적으로 다음과 같이 정의한다.

def func( arg1, arg2 ) : ...
func(1, 2)
  • 위치 인자의 특수한 케이스로 *연산자를 활용한 *my_list가 있다. *연산자의 *[인자]용법①iterable객체를 튜플로 변환하여 ②위치 인자로써 함수에 전달한다.
my_list = [ 3, 5 ]
func( *my_list )	#func(3, 5)와 동일하다.
  • 키워드 인자의 특수한 케이스로 **연산자를 활용한 **my_dict가 있다. **연산자의 **[인자]용법①dict객체를 키와 값으로 분해하여 ②키워드 인자로써 함수에 전달한다.
my_dict = [ 'args1' = 3, 'args2' = 5 ]
func( **my_dict )	#func('args1' = 3, 'args2' = 5)와 동일하다.

1.1. 디폴트 값을 가진 매개변수

함수를 정의할 때 매개변수에 디폴트 값을 지정할 수 있다. 디폴트 값을 가진 매개변수는 선택적인 인자로 함수를 호출할 때 전달하지 않더라도 디폴트 값을 이용해 성공적으로 작동한다.

def func( arg1, arg2 = True ) : ...
func(1)		#func(1, True)와 같다.
func(1, arg2 = False)

이렇게 지정된 디폴트 값을 가진 매개변수는 키워드 인자로 접근하는 것이 좋다. 왜냐하면 함수의 매개변수를 수정할 때 ①디폴트 값을 가지고 ②매개변수 중 맨 뒤에 추가하는 것이 함수의 하위 호환성 측면에서 유연하다. 그런데 위치 인자는 *구조적으로 뒤 쪽에 놓일 수 없기 때문이다.

2. 가변 인자를 받을 수 있는 매개변수: *args, **kwargs

  • *args를 매개변수로 지정하면 가변 위치 인자(선택적, 가변적)를 받을 수 있다.
    • 인자의 개수가 처리하기 좋을 정도로 충분히 작다는 사실을 이미 알고 있는 경우 사용
    • *args 이후에 오는 매개변수는 모두 키워드 인자로만 접근 가능함
 def func(arg1, arg2, *args): ...
 
 my_list = [x for x in range(50)]
 func(1, 2, *my_list)

💩 가변 위치 인자를 받는 매개변수 *args사용의 문제점
1. *연산은 모든 Iterable(제너레이터 마저)을 튜플로 변환하므로 과도한 메모리 사용 가능성
2. 위치 인자를 받는 새로운 매개변수를 추가할 경우 반드시 * 앞에 추가해야하고 호출자를 모두 변경해야함 ⇒ 새로운 매개변수는 키워드 인자를 받도록 추가할 것

  • **kwargs를 매개변수로 지정하면 가변 키워드 인자(선택적, 가변적)를 받을 수 있다.
    • **kwargs 이후에 오는 매개변수는 모두 키워드 인자로만 접근 가능함
 def func(arg1, arg2, *kwargs): ...
 
 my_dict = {key : value for key, value in enumerate(range(50,100), 1)}
 func(1, 2, **my_dict)

🥰 불변/가변 키워드 인자 사용의 장점
1. 명확한 의미전달
2. 디폴트 값을 가진 매개변수 사용 가능
⇒ 하위 호환성backward compatibility 만족, 마이그레이션(대대적인 수정) 불필요

3. 기타

3.1. 위치인자와 키워드 인자의 명시적 구분: /, *

  • / 앞: 위치 인자로만 접근 가능한 매개변수
  • * 뒤: 키워드 인자로만 접근 가능한 매개변수
 def func(arg1, arg2, /, ndigits=10, *, ignore_overflow=False, ignore_zero_division=False):

3.2. 디폴트 값을 가진 매개변수의 동적 할당: None

디폴트 값으로 바로 전달하지 않는다. 함수 또는 mutable의 경우 더욱 주의해야한다.

 def decode(data, default = None):
 	'''문자열로부터 JSON 데이터를 읽어온다.
    	Args:
        	data: ...
            	default: ...
                	 디폴트 값은 빈 딕셔너리 이다.
        '''
       try: ...
       except ... :
       	if default is None:
        	default = {}
	return default

😎 끝.

profile
현직 데이터 분석가 / 데이터 과학의 정도를 따라 🚲 / About DEV DA ML

0개의 댓글