Home 파이썬 코딩의 기술(3) 함수
Post
Cancel

파이썬 코딩의 기술(3) 함수

  • 책 파이선 코딩의 기술을 읽고 정리한 내용입니다. Book_Logo

3. 함수

19. 함수가 여러 값을 반환하는 경우 절대로 네 값 이상을 언패킹하지 말라

함수의 값을 언패킹할 때 변수가 네 개 이상 나오면 실수하기 쉽다.


20. None을 반환하기보다는 예외를 발생시켜라

특별한 의미를 표시하는 None을 반환하는 함수를 이용하면, 다른 값(0 또는 [] 등등)과 None을 구별하기 힘들어진다.
None 대신 예외를 발생시켜서 예외처리를 해주면 된다.


21. 변수 영역과 클로저의 상호작용 방식을 이해하라

코드에서 어떤 변수를 참조할 때, 파이썬 인터프리터는 이를 위해 다음 순서로 영역을 뒤진다.

  1. 현재 함수의 영역
  2. 현재 함수를 둘러싼 영역
  3. 현재 코드가 들어있는 모듈의 영역(전역 영역)
  4. 내장 영역(len, str 등이 있는 영역)

그러나, 코드에서 변수에 값을 대입하는 것은 다른 방식으로 작동한다.
변수가 현재 영역에 이미 정의되어 있지 않다면, 파이선은 변수를 새로 정의하는 것으로 판단한다.
따라서 똑같은 이름의 변수가 2개 생기게 된다.

1
2
3
4
5
6
7
8
9
def sort_priority2(numbers, group):
    found = False
    def helper(x):
        if x in group:
            found = True # 새로운 변수 found가 helper() 함수 내부에서 정의된다.
            return (0, x)
        return (1, x)
    numbers.sort(key=helper)
    return found

22. 변수 위치 인자를 사용해 시각적인 잡음을 줄여라

함수 정의에서 *args를 통해 가변위치 기반 인자를 받을 수 있다. 즉 여러개의 인자를 하나의 tuple로 패킹할 수 있다.
이미 값이 시퀀스인 경우, *를 통해 시퀀스를 언패킹한후, 가변인자를 받는 함수에게 전달할 수 있다.
제네레이터에 *연산자를 사용하면 메모리를 많이 소비할 수 있다.


23. 키워드 인자로 선택적인 기능을 제공하라

위치기반 인자는 키워드 인자보다 항상 앞에 지정해야 한다.
함수 정의에서 **kwargs를 통해 키워드 인자를 딕셔너리로 패킹할 수 있다.
**연산을 통해 딕셔너리에 있는 값을 함수에 키워드 인자로 전달할 수 있다.
키워드인자는

  1. 함수 호출의 의미를 명확하게 보여주고
  2. 인자의 디폴트값을 정할 수 있고
  3. 하위 호완성을 제공한다.

24. None과 독스트링을 사용해 동적인 디폴트 인자를 지정하라

디폴트 인자가 동적인 경우, 함수의 정의에서 한번만 초기화되기 때문에 오류가 발생할 수 있다.

1
2
3
4
5
6
7
8
9
10
def decode(data, default={}):
    try:
        return json.loads(data)
    except ValueError:
        return default

foo = decode('잘못된 데이터')
foo['stuff'] = 5
bar = decode('또 잘못된 데이터')
bar['meep'] = 1

25. 위치로만 인자를 지정하게 하거나 키워드로만 인자를 지정하게 해서 함수 호출을 명확하게 만들라

  • 기호는 위치 인자의 마지막과 키워드만 사용하는 인자의 시작을 구분해준다.
    / 기호는 위치로만 지정하는 인자의 끝을 표시한다.
    이 두 기호의 사이에는 두 가지 방식의 인자가 들어올 수 있다.
    이를 통해 함수의 안정성을 강화할 수 있다.
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    
    def safe_division_d(numerator, denominator, /, *,
                      ignore_overflow=False,
                      ignore_zero_division=False):
      try:
          return numerator / denominator
      except OverflowError:
          if ignore_overflow:
              return 0
          else:
              raise
      except ZeroDivisionError:
          if ignore_zero_division:
              return float('inf')
          else:
              raise
    

26. functools.wrap을 사용해 함수 데코레이터를 정의하라

데코레이터를 통해 함수를 변경하지 않고 감쌈을 통해 추가 구현을 해줄 수 있다.
그러나 데코레이터를 사용하면 인트로스펙션을 생성하는 도구가 잘못 작동할 수 있기때문에, functools.wraps를 추가로 사용해줘야 한다.

1
2
3
4
5
6
7
8
9
10
11
12
13
from functools import wraps

def trace(func):
    @wraps(func)
    def wrapper(*args, **kwargs):
        result = func(*args, **kwargs)
        print(f'{args!r} -> {result!r}')
        return result
    return wrapper

@trace
def fibonacci(n):
    ...
This post is licensed under CC BY 4.0 by the author.

파이썬 코딩의 기술(1) 파이썬답게 생각하기

파이썬 코딩의 기술(2) 리스트와 딕셔너리