Develop/Computer Science

[Python] 함수 (2/2)

세미제로 2024. 1. 14. 00:07

본 포스팅은 "파이썬 코딩의 기술(브렛 슬라킨 외 저)"를 보고 작성했습니다.

파이썬 주니어들이 시니어로 발돋움하기 위한 최고의 책이라고 생각되네요!!

 https://www.gilbut.co.kr/book/view?bookcode=BN002890 

 

Effective Python 2nd 이펙티브 파이썬 : 파이썬 코딩의 기술

똑똑하게 코딩하는 법, 개정판

www.gilbut.co.kr


파이썬 함수에는 프로그래머가 더 편하게 프로그래밍할 수 있도록 해주는 여러가지 추가 기능이 들어있다. 

이런 추가 기능을 사용ㅎ면 함수의 목적을 더 분명하게 표현할 수 있고, 코드의 잡음을 줄여서 함수 호출의 의도를 더 명확히 드러낼 수 있으며, 찾기 어려운 미묘한 버그를 현저히 줄일 수 있다.


BETTER WAY 5  "키워드 인자로 선택적인 기능을 제공하라"

  • ** 연산자는 파이썬이 딕셔너리에 들어 있는 값을 함수에 전달하되 각 값에 대응하는 키를 키워드로 사용하도록 명령한다.
  • ** 연산자를 위치 인자나 키워드 인자와 섞어서 함수를 호출할 수 있다. 다만 중복되는 인자가 없어야 한다.
  • ** 연산자를 여러 번 사용할 수도 있다. 다만 여러 딕셔너리에 겹치는 키가 없어야 한다.
def remainder(number, divisor):
    return number % divisor
    
remainder(20,7)
>>> 6

#키워드 인자를 활용할 경우
my_kwargs = {
    'number' : 20,
    'divisor' : 7,}

remainder(**my_kwargs)
>>> 6
  • 키워드 인자가 제공하는 유연성을 활용하면 세 가지 큰 이점이 있다
    1. 키워드 인자를 사용하면 코드를 처음 보는 사람들에게 함수 호출의 의미를 명확히 알려줄 수 있다.
    2. 키워드 인자의 경우 함수 정의에서 디폴트 값을 지정할 수 있다.
    3. 어떤 함수를 사용하던 기존 호출자에게는 하위 호환성을 제공하면서 함수 파라미터를 확장할 수 있는 방법을 제공한다는 것이다.

BETTER WAY 6  "None과 독스트링을 사용해 동적인 디폴트 인자를 지정하라"

  • 종종 키워드 인자의 값으로 정적으로 정해지지 않는 타입의 값을 써야 할 때가 있다.
  • 동적인 값을 가질 수 있는 키워드 인자의 디폴트 값을 표현할 때는 None을 사용하라
  • 그리고 함수의 독스트링에 실제 동적인 디폴트 인자가 어떻게 동작하는지 문서화해두라.
def log(message, when=None):
    """메시지와 타임스탬프를 로그에 남긴다.
    
    Args:
        message: 출력할 메시지.
        when: 메시지가 발생한 시각(datetime)
            디폴트 값은 현재 시간이다.
    """
    if when is None:
        when = datetime.now()
    print(f'{when}: {message}')

 

 결코 None을 반환하지 않도록 수정

def careful_divide(a, b):
    try:
        return a/b
    except ZeroDivisionError as e:
    	raise ValueError('잘못된 입력')

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

[키워드 인자]

  • 키워드로만 지정해야 하는 인자를 사용하면 호출하는 쪽에서 특정 인자를 반드시 키워드를 사용해 호출하도록 강제할 수 있고,
  • 이로 인해 함수 호출의 의도를 명확히 할 수 있다.
  • 키워드로만 지정해야 하는 인자는 인자 목록에서 *다음에 위치하도록 하자

[위치 인자]

  • 위치로만 지정해야 하는 인자를 사용하면 호출하는 쪽에서 키워드를 사용해 인자를 지정하지 못하게 만들 수 있고,
  • 이에 따라 함수 구현과 함수 호출 지점 사이의 결합을 줄일 수 있다.
  • 위치로만 지정해야 하는 인자는 인자 목록에서 / 앞에 위치하도록 하자

BETTER WAY 8 "functools.wrap을 사용해 함수 데코레이터를 정의하라"

  • 파이썬은 함수에 적용할 수 있는 데코레이터(decorator)를 정의하는 특별한 구문을 제공한다.
  • 데코레이터는 자신이 감싸고 있는 함수가 호출되기 전과 후에 코드를 추가로 실행해준다.
  • 데코레이터를 활용하면, 아래의 상황에서 유용하게 활용할 수 있다
    1. 함수의 의미를 강화하거나
    2. 디버깅을 하거나
    3. 함수를 등록하거나
  • 직접 데코레이터를 구현할 때 인트로스팩션에서 문제가 생기지 않길 바란다면, functools 내장 모듈의 wraps 데코레이터를 사용하면 조금 더 효율적이다!!
from functools import wraps

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

@trace
def fibonacci(n):
    """n번째 피보나치 수를 반환한다."""
    if n in (0,1);
        return n
    return (fibonacci(n-2) + fibonacci(n-1))