IT/언어

[python] python의 함수 인수(인자) 정리

개발자 두더지 2020. 8. 19. 13:57
728x90

1. 함수를 사용할 때

번호 Syntax 기능
1 func(value) 보통의 호출로, 함수 호출과 인수의 위치가 짝이 됨
2 func(name = vlaue) 키워드에 대응하는 함수 호출
3 func(*iterable) iterable한 것을 전개하여 함수 호출
4 func(**dict) dict를 key,vlaue로 전개해 함수 호출(2의 인수를 dict로하여 전달)

 

2. 함수를 정의할 때

번호 Syntax 기능
1 def func(name) 보통의 함수정의, 함수호출과 인자의 위치가 짝이됨
2 def func(name=value) 인수에 초기값을 설정
3 def func(*name) 인수를 튜플로 함
4 def func(**name) 인수를 dictionary로 함
5 def func(*arg, name) name만은 지정할 필요가 있음 (버전 3 이상)
6 def func(*, name=vlaue) 인수를 모두 지정할 필요가 있는 것으로 함 (버전 3이상)

 

■ 기본 인수

 일반적으로 함수 호출할 때 전달하는 값을 인수(인자)라고 하는데, 파이썬에서는 인수를 넘겨주지 않아도 인수가 자신의 기본 값을 취하도록 하는 기능이 있다. 함수 오버로딩을 지원하는 언어에서는 이를 여러개 취하는 형식으로 지원하는데 파이썬은 조금 독특한 방법을 사용한다. 

 다른 언어와 달리 파이썬은 인자를 생략할 수도 있고, 인자의 순서를 마음대로 변경하여 지정할 수 있다. 더욱이 함수에서 어떤 인자를 받을지 이름과 갯수를 정하지 않고서도 함수를 정의할 수 있다. (물론 다른 언어에서 비슷한 기능을 제공하고 있긴 하다.)

def add(a, addto=1):
	return a + aato

b = 1
b = add(b)
print(b) # 2

b = add(b, 10)
print(b) # 11

 위와 같은 방식으로 동작하는데, 함수 add의 두 번째 인수 addto는 이 함수를 호출할 때 특정값을 넘겨주지 않으면 기본적으로 1을 사용한다.

 한 가지 주의할 점은, 초기값을 가지는 인수는 인수 목록 중에 마지막에 위치해야 한다. 즉 아래의 코드는 동작하지 않고 non-default argument 문법 에러를 출력한다.

def add(addto = 1, a) :
	return a + addto

a = 1
b = add(b)
print(b)

# SyntaxError: non-default argument follows default argument

 

■ 키워드 인수

함수 호출시 인수의 이름을 지정하여 값을 전달하는 방식이다. 이 방식은 인자의 이름에 전달하고자 하는 값을 직접 지정하여 호출한다. 뒤에서 설명하겠지만, 함수 호출시 인자의 순서는 1순위로 순서에 의한 매칭이 완료되고 나서 키워드 인수 매칭이 되기 때문에 순서 지정에 신경써야 한다.

def area(h,w):
	return h * w

a = area(w = 20, h = 10)
print(a) # 200

b = area(h = "Height", w = 3)
print(b) # Height Height Height

그러나 함수 호출시 순서에 의한 매칭이후 키워드 인수 매칭을 수행하기 때문에, 아래의 코드는 동작하지 않는다. h는 순서에 의한 매칭, w는 키워드 인수 매칭이기 때문에 반드시 area(10, w=20)만 동작한다. 키워드 인수 매칭 사이에서의 순서는 상관없이 동작한다.

def area(h,w):
  return h*w

c = area(w=20, 10)

# File "<ipython-input-21-fd6c046e6cf7>", line 4
#    c = area(w=20, 10)
#                  ^
# SyntaxError: positional argument follows keyword argument

 

■ 가변 인수 리스트

 어떤 함수를 설계할 때, 몇 개의 인수를 받게 될지 모를 때가 있다. 이때 일반적으로 생각하는 방법은 두 가지이다.

① 최대한 필요한 인수를 예상한 후 각 인수 갯수를 가지는 함수를 만든다.

▶ 비효율적이며, 최대 갯수를 넘어가는 경우가 발생하면 대처가 어렵다.

② 가변으로 받아야 하는 인수를 배열이나 리스트로 선언하고, 이를 넘기도록 한다.

②의 방법을 함수 내에서 자체 지원하는 것이 가변 인수 리스트이다. 함수를 정의할 때, 인수 리스트에 반드시 넘겨야하는 고정 인수들을 나열하고, 나머지는 튜플 형식으로 한꺼번에 받는다. 

def function(a, *args):
  print(a, args)

function(1) # 1 ()
function(1,2) # 1 (2,)
function(1,2,3,4,5) # 1 (2, 3, 4, 5)
function(1,2,3,4,5,'a','b',[6,7,8],{'a':3, 'b':8}) # 1 (2, 3, 4, 5, 'a', 'b', [6, 7, 8], {'a': 3, 'b': 8})

첫 번째 인수 a는 항상 넘겨준대로 받고, 두 번째 인자부터는 인자들을 묶은 튜플 형식으로 받는다. 따라서 넘겨주는 임자의 데이터 형이 무엇이든 상관없다. 일반적으로 function에서는 넘겨 받은 args의 길이를 카운트한 후 그에 맞는 동작을 하면 된다. 

 

■ 정의되지 않은 키워드 인수 처리하기

 키워드 인수를 이용하여 함수를 호출할 때, 만일 미리 정의되어 있지 않은 키워드 인수를 받으려면 함수를 정의할 때 마지막에 **kw 형식으로 기술한다. **kw는 {키:값}형태의 사전형식으로 전달되며, 키는 키워드(변수명)이 되고, 값은 키워드 인수로 전달된 값이다.

def addAll(width, height, **kw):
  all = width + height
  print(width, height, kw)

addAll(10, 20, size=15, depth=35) # 10 20 {'size': 15, 'depth': 35}

 함수의 가인수로 정의된 width와 height외에는 kw에 사전형태로 전달됐다. 주의할 점은 사전 키워드 인수는 함수의 가인수 목록의 제일 끝에 작성되어야 한다. (가변 인수 리스트보다도 뒤에 작성되어야 한다.) 

def addAll(width, height, **kw):
  all = width + height
  print(width, height, kw)

dargs = {'depth':35, 'size':15}
addAll(10, 20, **dargs) # 10 20 {'depth': 35, 'size': 15}

 

※ 표의 5, 6번에 대해 조금 더 자세한 설명

5와 6은 한 번에 파악하기 힘들다.

Python의 함수호출에서는 name=value로써 호출하지만, def function(name)만은 함수호출 쪽에서 name=vlaue로 할까 value만을 전달할지 자유롭게 할 수 있으므로 코드에서는 혼란이 생긴다. 이러한 문제를 해소하기 위해 버전 3부터는 이것을 강제하는 syntax가 생겼다. (아마도)

① 5번에 대해

5는 name=vlaue를 강제하는 것과 그렇지 않은 것을 공존하게 할 수 있다.

아래의 코드에서 c만을 name=vlaue의 형식을 강제하고 있다.

In [18]: def kwonly(a, *b ,c):
   ....:     print(a, b, c)
   ....:

In [19]: kwonly(1,2,3)
---------------------------------------------------------------------------
TypeError                                 Traceback (most recent call last)
<ipython-input-19-763cbb52b1ed> in <module>()
----> 1 kwonly(1,2,3)

TypeError: kwonly() missing 1 required keyword-only argument: 'c'
# cはname = valueでしか値が渡せない


In [20]: kwonly(1, 2, c=3)
1 (2,) 3

② 6번에 대해

5번과 거의 비슷하지만, 전부를 name=vlaue로 하는 한편, 초기값을 정해두자는 것이다. 당연히 초기값이 없어도 괜찮으며 가능하면 초기값을 설정해두자는 의미정도이다.

In [21]: def kwonly2(*, b , c=3):
   ....:     print(b,c)
   ....:

In [22]: kwonly2(1)
---------------------------------------------------------------------------
TypeError                                 Traceback (most recent call last)
<ipython-input-22-ace6c6f57de4> in <module>()
----> 1 kwonly2(1)

TypeError: kwonly2() takes 0 positional arguments but 1 was given
# そもそも1が引数として認識されていない

In [23]: kwonly2(b=1)
1 3

In [24]: kwonly2(b=1,2)
  File "<ipython-input-24-6c15c1f279e8>", line 1
    kwonly2(b=1,2)
               ^
SyntaxError: non-keyword arg after keyword arg
# cはname = valueでしか渡せない(もちろんbも)


In [25]: kwonly2(b=1,c=2)
1 2

참고자료

https://m.blog.naver.com/resumet/221444971512

https://qiita.com/rsakamot/items/6d809bed894d2b430aad

 
728x90