ABOUT ME

-

Today
-
Yesterday
-
Total
-
  • TIL.26 함수 매개변수 및 인수
    TIL 2020. 11. 3. 17:39
    728x90

    # 함수에서 위치 인수와 키워드 인수 사용하기

    ## 위치 인수와 리스트 언패킹

    ## 위치 인수(positional argument) : 

    아래와 같이 함수에 인수를 순서대로 넣는 방식을 위치 인수라고 한다. 인수의 위치가 정해져있다는 뜻이다.

    print(1, 2, 3)

    # 우리가 사용하는 흔한 방식

    ## 위치 인수를 이용해 함수를 만들고 호출해보자.

    def aaa (a, b, c):
        print(a)
        print(b)
        print(c)
    
    aaa(1, 2, 3)
    ::
    1
    2
    3

    ## 언패킹 사용하기

    ## 위에서 만든 함수에서 언패킹을 사용해보자

    ## 아래와 같이 리스트 또는 튜플 앞에 *(애스터리스크)를 붙여 함수에 넣어주면 된다. (함수를 호출 할때)

    # 함수(*리스트)

    # 함수(*튜플)

    def aaa (a, b, c):
        print(a)
        print(b)
        print(c)
        
    x = [10, 20, 30]
    # aaa(x) ## error  
    # aaa([10, 20, 30]) ## error
    
    aaa(*x)
    aaa(*[10, 20, 30]) 
    ::
    10
    20
    30

    # aaa(x) ## error  
    # aaa([10, 20, 30]) ## error

    ## 이때 함수의 매개변수 개수와 리스트의 요소 개수가 같아야 한다. 다를 경우 함수를 호출 할 수 없다.

    # TypeError: aaa() missing 2 required positional arguments: 'b' and 'c' //

    2개의 매개변수가 더 필요하다는 내용의 에러가 뜸을 확인할 수 있다.


    ## 위치 인수와 리스트 언패킹 기능을 이용해 인수의 개수가 정해지지 않은 가변 인수에 사용 할 수 있다.

    ## 가변 인수 (variable argument) : 인수의 개수가 정해지지 않은, 인수의 개수를 제한하지 않는, 방식을 가변 인수라 한다.

    ## 가변 인수는 인수를 1개, 10개 또는 아무것도 넣지 않을 수 도 있다.

    매개 변수 앞에 *(애스터리스크)를 사용하면 된다. (함수를 생성할때)

    # def 함수이름(*매개변수):

    #     코드

    def bbb (*args):
        for arg in args:
            print(arg)
    
    bbb(10, 20, 30, 40, 50)
    ::
    10
    20
    30
    40
    50
    
    y = [10, 20, 30]
    bbb(y) 
    ::
    [10, 20, 30]
    
    bbb(*y)
    ::
    10
    20
    30
    
    x = [10]
    bbb(x)
    ::
    [10]
    bbb(*x)
    ::
    10
    
    

     

    ## 함수를 만들때 매개변수의 이름은 관례적으로 arguments 를 줄인 , "args"를 사용한다.

    ## 이 (args)는 튜플 형식으로 for 문으로 반복할 수 있다.


    ## 고정 인수와 가변 인수 함께 사용하기

    def ccc (a, *args):
        print(a)
        print(args)
    
    ccc(1)
    ::
    1
    () # args에 인수를 입력하지 않았다.
    
    ccc (10, 100, 200, 300)
    ::
    10
    (100, 200, 300)

    ## 여기서 ccc(*args, a) 와 같이 가변인수는 고정 인수 보다 앞쪽에 위치하면 안된다.

    ## 반드시 매개변수 순서에서 *args는 가장 뒤쪽에 있어야 한다.


    ## 키워드 인수 사용하기

    ## 사용자의 개인정보를 출력해주는 함수를 예로 들어보자.

    def personal_info(name, age, address):
        print('이름: ', name)
        print('나이: ', age)
        print('주소: ', address)
    

    ## 내가 만든 함수에서는 매개변수 1 ,2, 3이 무엇인지 알고 있어, 함수를 호출 할 경우 인수에 (이름, 나이, 주소)라는 인수를 넣어 함수를 호출하였지만

    ## 매번 함수 생성 당시 각각의 인수가 무슨 용도인지 직접 만든사람이 아니면, 알기가 어려웠다.

    ## personal_info(30, 홍길동, 서울)을 입력할 경우 이름은 30이 되고, 나이는 홍길동이 된다.

    ## 이러한 불편을 줄이기 위해 파이썬에서는 "키워드 인수"를 제공한다.

    ## 함수(키워드=값)

    personal_info(name='홍길동', address='서울', age=30)
    ::
    이름:  홍길동
    나이:  30
    주소:  서울

    ## 키워드 인수는 함수 호출 시 사용한다.

    ## 위 처럼 이름, 나이, 주소 의 순서가 아니여도 키워드 인수로 인해 해당하는 값이 정상적으로 들어가게 된다.

    # 추가, 여지껏 키워드 인수는 많이 사용해온 것을 알 수 있다.

    print(123sep=':'end=''## 매번 사용하던 sep, end 도 키워드 인수이다. 


    ## 키워드 인수와 딕셔너리 언패킹 사용하기

    ## 딕셔너리를 사용한 키워드 인수 값 넣기

    ## 함수 호출 시 딕셔너리 앞에 ** (애스터리스크)2개를 붙혀주면 된다.

    ## 함수(**딕셔너리)

    def personal_info(name, age, address):
        print('이름: ', name)
        print('나이: ', age)
        print('주소: ', address)
    
    x = {'name': '홍길동', 'age': 30, 'address': '서울시 용산구 이촌동'} 
    personal_info(**x)
    ::
    이름:  홍길동
    나이:  30
    주소:  서울시 용산구 이촌동
    
    personal_info(**{'name': '홍길동', 'age': 30, 'address': '서울시 용산구 이촌동'})
    ::
    이름:  홍길동
    나이:  30
    주소:  서울시 용산구 이촌동

    ## 딕셔너리 변수 또는 딕셔너리 앞에 바로 **를 붙혀도 동작한다.

    ## 딕셔너리를 이용해 키워드 인수를 사용하기 위해선 몇가지 조건이 필요하다.

    # 1. 딕셔너리 언패킹 사용시 함수의 매개변수 이름과 딕셔너리의 키 이름이 같아야 한다. 

    # 2. 매개변수의 개수와 딕셔너리 키의 개수도 같아야 한다, 이름 또는 개수가가 다르면 함수를 호출 할 수 없다.

    # 3. 딕셔너리 키는 반드시 "문자열" 형태여야 한다.

    ## **(애스터리스크)를 2번 사용하는 이유

    ## 가장 큰 이유는 딕셔너리가 키 - 값 쌍의 형태로 값이 저장되어 있기 때문이다.

    def personal_info(name, age, address):
        print('이름: ', name)
        print('나이: ', age)
        print('주소: ', address)
    
    x = {'name': '홍길동', 'age': 30, 'address': '서울시 용산구 이촌동'} 
    personal_info(*x)
    ::
    이름:::  name
    나이:  age
    주소:  address
    
    personal_info(**x)
    ::
    이름:  홍길동
    나이:  30
    주소:  서울시 용산구 이촌동

    ## 애스터리스크를 1개만 사용할 경우  위와 같이 x의 "키" 값만 출력된다.

    ## 즉, 딕셔너리의 키 값만을 출력하고 싶다면 애스터리스크를 1번만 사용하면 된다.

    (딕셔너리를 1번 언패킹하면 키가 사용된다는 뜻)

    ## 애스터리스크를 2번 사용하여 값을 사용하도록 만들어 준다.(딕셔너리 2번 언패킹하면 값이 사용된다는 뜻)


    ## 키워드 인수를 사용하는 가변 인수 함수 만들기

    ## 매개변수 앞에 ** 2개를 사용하면 된다.

    def 함수이름(**매개변수):

    #     코드

    def aaa (**kwargs):
        for kw, arg in kwargs.items():
            print(kw, ':', arg)

     

    ## 매개 변수 이름은 관례적으로 keyword arguments를 줄여 kwargs를 사용한다.

    ## 특히 이 kwargus는 딕셔너리로 for 반복문으로 반복할 수 있다.

    def aaa (**kwargs):
        for kw, arg in kwargs.items():
            print(kw, ':', arg)
            
    aaa(name='홍길동')
    ::
    name : 홍길동
    
    aaa(name='홍길동', age=30, address='서울시 용산구 이촌동')
    aaa(**x)
    ::
    name : 홍길동
    age : 30
    address : 서울시 용산구 이촌동

    ## 인수를 직접 넣어도 가능하며 딕셔너리 언패킹을 사용해도 된다.

    ## 인수와 딕서녀리 언패킹을 사용해도 값이 같음으로 

    # 딕셔너러 x ={'name': '홍길동'} 일때는 ->

       add(**x) == add(name='홍길동')

    # 딕셔너러 x ={'name': '홍길동', 'age': 30, 'address': '서울시 용산구 이촌동'} 일때는 -> 

       add(**x) == add(name='홍길동', age=30, address='서울시 용산구 이촌동')으로 서로 같다는 걸 알 수 있다.

    # 이처럼 함수를 만들 때 def personal_info(**kwargs):와 같이 매개변수에 **를 붙여주면 키워드 인수를 사용하는 가변 인수 함수를 만들 수 있다.

    # 그리고 이런 함수를 호출할 때는 키워드와 인수를 각각 넣거나 딕셔너리 언패킹을 사용하면 된다.

    ## 보통 **kwargs를 사용한 가변 인수 함수는 아래와 같이 함수 안에 특정 키가 있는지 확인 뒤 해당 기능을 만든다.

     

    def personal_info(**kwargs):
        if 'name' in kwargs:    # in으로 딕셔너리 안에 특정 키가 있는지 확인
            print('이름: ', kwargs['name'])
        if 'age' in kwargs:
            print('나이: ', kwargs['age'])
        if 'address' in kwargs:
            print('주소: ', kwargs['address'])

    ## 고정 인수와 가변인수(키워드 인수)를 함께 사용하기

    def personal_info_1(name, **kwargs):
        print(name)
        print(kwargs)
    
    personal_info_1('홍길동')
    ::
    홍길동
    {}          # 키워드 인수 아무것도 넣지 않음
    
    personal_info_1('문타리', age=30, address='서울시 용산구 이촌동')
    ::
    문타리
    {'age': 30, 'address': '서울시 용산구 이촌동'}.
    
    personal_info_1(**{'name': '홍길동', 'age': 30, 'address': '서울시 용산구 이촌동'})
    ::
    홍길동       # 앞에 문타리, 를 넣어줄 경우 고정인수 충돌
    {'age': 30, 'address': '서울시 용산구 이촌동'}

    ## 위치 인수와 키워드 인수 함께 사용하기

    def custom_print(*args, **kwargs):
        print(*args, **kwargs)
    
    custom_print(1, 2, 3, sep=':', end='')
    ::
    1:2:3

    ## 이때 def custom_print(**kwargs, *args):처럼 **kwargs가 *args보다 앞쪽에 오면 안 된다.

    ## 매개변수 순서에서 **kwargs는 반드시 가장 뒤쪽에 와야 한다.

    ## 특히 고정 매개변수와 *args, **kwargs를 함께 사용한다면 

    ## def custom_print(a, b, *args, **kwargs):처럼 매개변수는 고정 매개변수, *args, **kwargs 순으로 지정해야 한다.


    ## 매개변수에 초깃값 지정하기

    ## 함수를 호출 할때 항상 인수를 넣어 값을 전달하였다. 그렇다면 인수를 생략 할 수는 없을까?

    ## 이를 위해 함수를 정의할때 매개변수에 초깃값을 지정해주면 된다.

    ## 초깃값을 기본값으로 생각하여도 문제가 없을 것 같다. 

        왜냐하면 초깃값은 말그대로 초깃값으로 얼마든지 덮어씌워질 수 있기 때문이다.

    def personal_info(name, age, address='비공개'):
        print('이름: ', name)
        print('나이: ', age)
        print('주소: ', address)
    
    personal_info('홍길동', 30)
    ::
    이름:  홍길동
    나이:  30
    주소:  비공개
    
    personal_info('홍길동', 30, '서울시 용산구 이촌동')
    ::
    이름:  홍길동
    나이:  30
    주소:  서울시 용산구 이촌동

    ## 초기값이 지정된 매개변수의 위치

    def personal_info(name, address='비공개', age): ## error
        print('이름: ', name) 
        print('나이: ', age)
        print('주소: ', address)

    ## 매개변수에 초깃값을 지정해줄때는 순서 및 위치가 굉장히 중요하다.

    ## 위 코드에서 ('홍길동', 30)으로 호출 하였을때 30이 어디로 들어가야하는지 알 수 없기 때문이다.

    ## 즉, 초깃값이 지정된 매개변수는 아래와 같이 뒤쪽으로 몰아주면 된다.

    def personal_info(name, age, address='비공개'):
    
    def personal_info(name, age=0, address='비공개'):
    
    def personal_info(name='비공개', age=0, address='비공개'):

    # 참고// def personal_info(name='비공개', age=0, address='비공개'):와 같이 

      모든 매개변수에 초깃값을 지정하면 personal_info()처럼 인수를 넣지 않고 호출할 수 있다.

    ## 이처럼 함수 생성에서 사용되는 위치 인수, 키워드 인수에서는 

    ### 리스트(튜플) 이면 ( + 위치인수) ==> * (에스터리스크 1개)

    ### 딕셔너리 이면 ( + 키워드인수)==> ** (에스터리스크 2개)를 사용한다는 점만 기억하자!

    ### *args <==> 호출 시 인수 개수가 다양한 경우 (생성시 매개변수)

    ### **kwargs <==> 키워드 인수로 호출이 이루어졌을 경우 (생성시 매개변수)

    728x90

    'TIL' 카테고리의 다른 글

    TIL. 28 람다 표현식(lambda) 사용하기  (0) 2020.11.05
    TIL. 27 재귀 호출(recursive call)  (0) 2020.11.04
    TIL. 25 함수의 호출 과정  (0) 2020.11.02
    TIL. 24 함수 만들고 사용하기  (0) 2020.11.01
    TIL.23 N-gram 만들기  (0) 2020.10.31
Designed by Tistory.