ABOUT ME

-

Today
-
Yesterday
-
Total
-
  • 파이썬 심화: function parameter
    python 2022. 2. 12. 22:44

    function parameter

    Argument vs Parameter

    Semantics

    parameter

    함수 정의 시 parameter라고 부름
    def my_func(a, b):
        pass

    arguments

    • 함수 호출 시 arguments라고 부름
      x = 1
      y = "a"
      my_func(x, y)
    • 이때 x, y는 refernce 함수에 reference(주소값)을 넘긴다.

    Positional and Keyword Arguments

    • 함수 정의 혹은 호출 시 kwargs가 오면, 그 뒤는 무조건 kwargs여야한다.
      • def my_func(a=1, b, c) 불가능!
      • my_func(a=1, 2,3) 불가능!

    Unpacking Iterables

    튜플 정의 방법

    • 괄호 ()를 사용해도 튜플이지만, 아래처럼 해도 튜플이다.
    a = 1,2,3
    print(a)
    print(type(a))
    (1, 2, 3)
    <class 'tuple'>

    Packed Values

    • bundled되있는 values를 일컫는다.
    • list, tuple, str, set, dict 모두 packed values다.
    • in fact, any iterable can be considered a packed value

    Unpacking Packed Values

    a,b,c = [1,2,3]
    print(a,b,c)
    a,b,c = 10, 20, "hello"
    print(a,b,c)
    a,b,c = "XYZ"
    print(a,b,c)
    
    1 2 3
    10 20 hello
    X Y Z
    1
    2
    3
    4
    5

    Extended Unpacking

    The use case for *

    • 아래 3가지 경우는 모두 a에 1을, b에 나머지를 할당한다.

      l = [1,2,3,4,5,6]
      1)
      a = l[0]
      b = [1:]
      2)
      a, b = l[0], l[1:]
      3)
      a, *b = l
    • 3)처럼 *을 사용하면, l이 list가 아니어도 b의 타입은 무조건 list가 된다.

    • 아래 같은 것도 가능하다.

    a, *b, c = [1,2,3,4,5]
    print(a,b,c)
    
    a = [1,2,3]
    b = [4,5,6]
    c = [*a, *b]
    print(c)
    
    a = {"p": 1, "y": 2, "z": 10}
    b = {"t": 3, "h": 4, "z": 50}
    c = {**a, **b}
    print(c) # b의 z가 a의 z를 overwrote함을 주의하라.
    
    d1 = {"a": 1, "b": 2}
    print({"a": 10, **d1})
    
    a, *b, (c, *d) = [1,2,3, "python"]
    print(a,b,c,d)
    1 [2, 3, 4] 5
    [1, 2, 3, 4, 5, 6]
    {'p': 1, 'y': 2, 'z': 50, 't': 3, 'h': 4}
    {'a': 1, 'b': 2}
    1 [2, 3] p ['y', 't', 'h', 'o', 'n']

    *는 좌변에 딱 한번만 사용 가능하다!

    a, *b, *c = [1,2,3,4,5] 는 에러!

    **는 좌변에 사용 불가하다.

    *args

    • *args와 *는 다르다.
    • *는 positional args를 개수 상관없이 받겠다는 것이고,
    • * indicates the "end" of positional arguments
    • 아래처럼 정의하면 positional을 전혀 받지 않겠다는 뜻이 된다. b는 kwargs가 된다.
      def my_func(*, b):
        pass

    Parameter defaults: Beware

    • 함수 param에 default로 준 값은 runtime에 생성된다.
    • 이는 매우 중요한 사실이다. 아래 예시를 보자.
    • runtime에 datetime.now()가 생성됐기 때문에 3초 sleep이후에도 여전히 같은 값이다.
    from datetime import datetime
    from time import sleep
    def main(t=datetime.now()):
        print(t)
    
    main()
    sleep(3)
    main()
    
    2022-02-11 17:55:09.028305
    2022-02-11 17:55:09.028305
    • 위 문제를 해결하려면 항상 함수 호출 시 값을 넘겨주거나, 아래 예시처럼 함수 안에서 값을 정의해야한다.
    • 보통은 default value를 None으로 정의하는게 국룰이다.
    from datetime import datetime
    from time import sleep
    def main(t=None):
        t = t or datetime.now()
        print(t)
    
    main()
    sleep(3)
    main()
    2022-02-11 17:57:52.713788
    2022-02-11 17:57:55.719404

    default value: mutable object

    • defalut value에 list와 같은 mutable을 쓸땐 정말 조심하자.
    • 아래처럼 원치 않는 결과가 나올 수도 있다.
    • runtime시 li=[]가 생성되고, 이후 계속 li는 (args로 주어지지 않는이상) 계속 같은 메모리를 참조한다.
    def main(a, li=[]):
        li.append(a)
        return li
    
    res1 = main(1)
    print(res1)
    res2 = main(3)
    print(res2)
    print(res1)
    print(res1 is res2)
    
    [1]
    [1, 3]
    [1, 3]
    True
    # 해결책
    def main(a, li=None):
        li = li or []
        li.append(a)
        return li
    
    # 의도적으로 함수 param에 mutable을 줄 때도 있다.
    # cache를 반복적으로 쓰려면 아래처럼 해야함.
    def factorial(n, cache={}):
        if n < 1:
            return 1
        elif n in cache:
            return cache[n]
        else:
            print("calculate")
            res = n * factorial(n-1)
            cache[n] = res
            return res
    
    res = factorial(3)
    print(res)
    res = factorial(3)
    print(res)
    calculate
    calculate
    calculate
    6
    6

    'python' 카테고리의 다른 글

    python RecursionError: maximum recursion depth exceeded 발생시  (0) 2023.05.02
    파이썬 클린코드 3  (0) 2022.02.26
    파이썬 심화: 변수와 메모리  (0) 2022.02.12
    파이썬 클린코드 2  (0) 2022.02.12
    파이썬 클린코드 1  (0) 2022.02.12

    댓글

Designed by Tistory.