TIL - Wecode | python-함수(function)

한성봉·2021년 5월 14일
0

함수(Function)

함수는 일정한 작업을 수행하는 코드? 프로그램이라고도 할 수 있습니다.
일반적으로 수학시간에 배웠던 함수와 개념적으로는 동일하다고 할 수 있습니다. input을 입력하면 어떤 과정을 통해 output이 도출되는 간단한 로직입니다.

  • 함수를 사용하는 이유

    • 반복적인 코드, 조건문 등을 함수로 정의해 간단하게 사용하기 위해
    • 코드의 가독성을 높이기 위해(반복적인 코드들이 나열되어있으면 가독성이 떨어짐)

    함수의 로직은 간단하다. input으로 어떤 입력값을 넣고 계산을 통해 output이 출력되는 구조이다.
    파이썬에서는 input 을 parameter라 하고 output을 return 값이라고 한다.

    함수의 생성

def 함수명(parameter):
    문장1
    문장2
    ...
    문장n
    return

parameterreturn 값은 옵션이다. parameterreturn 값이 없는 함수도 존재한다.

함수는 생성만 한다고 값이 도출되지 않습니다. 함수의 호출로 값을 생성할 수 있습니다.

함수명()

위와 같이 코드를 작성해야 함수를 호출하는 것입니다.

Function parameters

함수의 파라미터가 전달되는 로직을 한번 살펴보자.

def text(a, b):
    print(f"{a} 수도는 {b}")

text("한국", "서울")

함수의 생성부터 호출까지 기본 구조이다. 결과값은 한국 수도는 서울이 출력된다.
f-string은 기본 문법 글에서 학습한 적이 있다.

  • parameter1 => a
  • parameter2 => b

함수의 호출에서 파라미터 값을 넣었더니 return값이 출력되었다.

Keyword Arguments

기본적인 함수 구조에서 파라미터 순서를 순서대로 주지 않아도 되는 방법이 있습니다.

def text(a, b):
    print(f"{a} 수도는 {b}")

text(b="서울", a="한국")

다음과 같이 작성해도 결과값은 동일합니다.
함수에 주어진 파라미터 순서대로가 아닌 파라미터에 값을 주어서 출력할 수 있습니다.
이 방식을 Keyword Arguments 방식이라고 합니다.
이 방식의 장점은 가독성이 높아지고 실수로 값을 섞어 입력해도 금방 찾을 수 있다는 것입니다.
기본 형식의 함수 호출로 작성했을 때 파라미터를 실수로 바꿔 입력했을 때 방대한 양의 자료에서는 바뀌었는지 실수했는지 찾기가 힘들 수 있습니다. 그렇기 때문에 파라미터에 값을 지정해놓으면 상대적으로 값이 바뀔 확률이 줄어듭니다.

Mixing positional arguments and keyword arguments

위에서 봤던 두 방법을 혼합하여 사용할 수 있습니다.
예시를 통해 살펴보겠습니다.

def text(a, b):
    print(f"{a} 수도는 {b}")

text("한국", b="서울")

여기서 중요한것은 keyword arguments 는 순서가 바뀌어도 상관 없지만 positional arguments 부분은 순서를 지켜줘야 한다는 것입니다.

def text(a, b):
    print(f"{a} 수도는 {b}")

text(b="서울", "한국")
SyntaxError: positional argument follows keyword argument

에러가 나는 이유는 keyword argumentpositional argument 보다 더 앞으로 위치되어 함수가 호출되었기 때문입니다.
Positional arguments는 순서를 지켜주어야 하는데 순서가 틀렸기 때문에 에러가 나는것입니다.

Parameter Default Value

함수를 정의할 때 파라미터에 기본값을 미리 정해놓을 수 있습니다.

def text(a="한국", b="서울"):
    print(f"{a} 수도는 {b}")

text() # 한국 수도는 서울
def text(a, b="서울"):
    print(f"{a} 수도는 {b}")

text("한국") # 한국 수도는 서울

둘 다 같은 값을 출력합니다. 기본값이 정해진 파라미터는 함수가 호출될 때 값이 넘겨지지 않아도 출력됩니다.

여기서 주의할 점은 default 값이 정의된 parameterdefault 값이 정의 되지 않은 parameter보다 먼저 위치해 있으면 안된다는 점입니다.

파라미터의 기본값 설정은 뒤에서 부터 해야합니다.

def text(a="한국", b):
    print(f"{a} 수도는 {b}")

text("서울") # SyntaxError: non-default argument follows default argument

fault value parameternon-default value parameter 앞에 정의하면 오류나는 이유는 파이썬 인터프리터가 코드를 읽을 때 어느 파라미터(a, b)가 생략된지 모른다는 것이다.

positional argumentskeyword arguments의 특성 때문에 그렇다 positional arguments 은 생략이 불가능하고 정해진 위치에 따라 인자를 전달해야한다. 그러나 keyword arguments의 경우 함수 선언시 디폴트값을 설정할 수 있으며, 만약 인자를 생략할 시 해당 디폴트값이 인자의 값으로 들어간다. 즉, 이 형태의 인자는 생략이 가능하다. 따라서, 여기서 알 수 있는건 keyword arguments의 경우 생략이 가능하기 때문에, positional arguments 이전에 선언될 수는 없다.

파이썬에서는 이런 문법을 허용하지 않고 있으면 뒤에 있는 파라미터에도 기본값을 설정해주어여지 오류가 생성되지 않는다.

위치 인수(positional arguments)와 가변 인수(variable length arguments)

가변 인수(variable length arguments)

위치인수는 위에서 살펴봤고 가변인수에 대해 알아보자.
*args (variable length arguments): 가변인수 란 인수의 개수가 변할 수 있다는 의미이며 임의의 개수의 인자를 튜플 형태로 저장한다. ('....','....')
*args의 이름은 *... 다른 이름을 사용하여도 무방하다.

  • 위치 인수와 가변 인수의 다양한 형태 학습을 통해 몇가지 문제해결을 해보자.
  1. 위치 인수(positional arguments)와 가변 인수(variable length arguments)의 위치를 참고하여 어떤 에러가 발생 하는지 확인하고, 에러를 고쳐 정상적으로 출력되는지 확인해보자.
def func_param_with_var_args(name, *args, age):
    print("name=",end=""), print(name)
    print("args=",end=""), print(args)
    print("age=",end=""), print(age)

func_param_with_var_args("정우성", "01012341234", "seoul", 20)
#TypeError: func_param_with_var_args() missing 1 required keyword-only argument: 'age'

위에서 봤던 디폴트값을 줬을 때 나는 오류랑 비슷한 맥락이다.
임의의 개수의 인자를 받기 떄문에 뒤에 오는 파라미터가 값을 전달받지 못한다. 해결방법은 두가지로 볼 수 있다.
가변인자 *argsage의 위치를 바꿔주면 된다. 하지만 그렇게 되면 print 호출문의 순서도 바꿔줘야 하는 단점이 있다.

두번째 방법으로는 ageposition argument 에서 keyword argument로 바꿔주면 된다.

def func_param_with_var_args(name, *args, age):
    print("name=",end=""), print(name)
    print("args=",end=""), print(args)
    print("age=",end=""), print(age)

func_param_with_var_args("정우성", "01012341234", "seoul", age=20)

# name=정우성
# args=('01012341234', 'seoul')
# age=20

가변 키워드 인수(variable length keyword arguments)

가변 키워드 인수(variable length keyword arguments):
임의의 개수의 키워드를 받는 인자이다. *kwargs 로 사용하고 전달받은 키워드 인자를 딕셔너리 형태로 저장한다. {'a': '강아지', 'b': '고양이'}

  1. 가변 키워드 인수 (variable length keyword arguments)의 위치를 보고 어떤 에러가 발생 하는지 확인하고, 에러를 고쳐 정상적으로 출력되는지 확인해보자.
def func_param_with_kwargs(name, age, **kwargs, address=0):
    print("name=",end=""), print(name)
    print("age=",end=""), print(age)
    print("kwargs=",end=""), print(kwargs)
    print("address=",end=""), print(address)

func_param_with_kwargs("정우성", "20", mobile="01012341234", address="seoul")
# SyntaxError: invalid syntax

고민해봤지만 왜 안될까? 라는 생각이 든다. 위치인자는 앞에 위치시켜 값을 잘 받게 해줬고 가변인자 뒤에 위치인자가 존재하는 것도 아니고 디폴트값을 줬기때문에 출력될 것만 같다. 하지만 안된다.
해볼 수 있는 시도는 **kwargsaddress의 자리를 바꿔 보는 시도를 해봤다 조금 허무하지만 잘 실행이된다.

def func_param_with_kwargs(name, age, address=0, **kwargs):
    print("name=",end=""), print(name)
    print("age=",end=""), print(age)
    print("kwargs=",end=""), print(kwargs)
    print("address=",end=""), print(address)

func_param_with_kwargs("정우성", "20", mobile="01012341234", address="seoul")
# name=정우성
# age=20
# kwargs={'mobile': '01012341234'}
# address=seoul

근데 여기서 의문점은 address에 이미 디폴트 값이 존재하는데 address=0은 뭐지? 라는 생각이 든다. 그래서 0을 지워봤다 당연히 똑같은 결과값이 도출될 것이다. 앞의 두 인자와 같은 위치인자로 바뀐것이다.

def  func(non-default parameter, default value parameter, 가변 키워드 인자)

다음과 같은 순서로 파라미터를 배치해야한다.

  1. 위치 인수와 키워드 가변 키워드 인수 (variable length keyword arguments)의 위치를 통해 조사해서 어떤 에러가 발생 하는지 확인하고, 에러를 고쳐 정상적으로 출력되는 결과를 블로그에 정리해 주세요.

마지막 문제를 한번 살펴보자.

def mixed_params(name="아이유", *args, age, **kwargs, address):
    print("name=",end=""), print(name)
    print("args=",end=""), print(args)
    print("age=",end=""), print(age)
    print("kwargs=",end=""), print(kwargs)
    print("address=",end=""), print(address)

mixed_params(20, "정우성", "01012341234", "male" ,mobile="01012341234", address="seoul")

이번에도 제자리를 한번 찾아보자. 일단 age,address,name 이 위치 인자로 보인다. 하지만 name은 디폴트값이 있으니 뒤로 뺴겠다. 1차시도
(age, address, name="아이유", *args, **kwargs) 의 순서로 출력했으나 실패.

일단은 두번째 값에 이름을 받아야하니 위치를 조금 조정하자.
(age, name="아이유", address, args, **kwargs)로 변경했다. 하지만 실패.
address값을 살펴보니 마지막에 있다. 그럼 일단 자리를 맞춰주기 위해 끝으로 보내야겠지만 가변키워드인자가 있기 때문에 그 앞에 위치시킨다.
(age, name="아이유",
args, address, **kwargs) 로 바꿧더니 잘 출력되었다.

참고 사이트를 찾아보니 Keyword-Only-Argument 라는 특수인수가 있는데 가변 위치 인수 뒤에 위치하며 non-default Keyword-Only-Argument 와 default Keyword-Only-Argument 로 나누고 가변 키워드 인수 앞에 위치한다.

0개의 댓글