Python tech/고급 파이썬 공부

파이써닉한 함수 만들기

콜레오네 2023. 4. 16. 19:59

함수 또한 파이썬스럽게 만들면 좋다.

함수 작성은 프로그래밍의 가장 중요한 부분 중 하나이기 때문에

규칙을 잘 준수하고, 사용하기 쉬운 함수를 만드는 것이 중요하다.

.

.

해당 포스팅은 [클린코드, 이제는 파이썬이다] 저서의 일부입니다.


함수명

  • 함수는 특정 동작을 수행하기 때문에 대부분 '동사'가 들어간다.
  • 명사도 대부분 들어가지만, 특정 모듈에서는 동사만 존재하기도 한다.
    • webbrowser 모듈에서 open() 함수는 당연히 웹브라우저를 열어주겠다는 의미이다.
  • 짧고 단순한 이름보단 길지만 무슨 기능인지 알 수 있는 함수명이 좋다.
  • 당연히 open, min, random, list 등 내장 함수와 중복되는 함수명을 사용하는건 옳지 않다.

함수 크기의 트래이드 오프

함수는 가능한 짧으면 좋고, 한 화면을 넘어갈 정도로 길면 어려워진다.
짧은 함수의 장점

  • 함수 코드 이해가 쉬움
  • 필요로하는 파라미터가 적음
  • 함수 외 코드에 미치는 영향이 적음
  • 예외가 적게 발생하며, 디버깅이 쉽다.

짧은 함수의 단점

  • 필요한 함수 개수가 늘어남
  • 더 복잡한 프로그램이 탄생함
  • 정확한 이름을 붙이기 어려움
  • 함수 간의 관계가 복잡해지고, 디버깅이 어려워짐

함수는 가능한 짧게, 대충 30라인 ~ 200라인 이하로 구성되면 좋다고 말한다.

필자의 의견으론,
코딩 테스트와 같이 하나의 단순한 문제를 풀기 위해서는
함수를 최대한 잘게 쪼개어서 작은 기능별로 구성하는 것이 좋다고 느낀다.
제한된 시간 내에서 그리 길지 않은 코드를 작성해야하는 상황이기에
함수를 잘게 쪼개면 디버깅도 쉽고 반복되는 문제를 쉽게 해결할 수 있다.

하지만 조금 더 복잡한 프로그램을 구성해야하는 현업에서는
너무 짦은 함수는 인터페이스 함수 등에만 사용하는 것이 좋은 것 같다고 느낀다.

파라미터와 인수

  • 파라미터 Parameter : def와 함께 함수를 구성할 때 필요한 변수들
  • 인수 argument : 함수를 호출하여 사용할 때 집어넣는 변수들
    이처럼 파라미터와 인수는 분명히 다른 용어이지만, 일반적으로 혼용하여 사용한다.
    그리고 혼용하여 사용하여도 다들 문맥상 알아듣곤 한다.

기본 인수
default value 를 세팅하는 것은 파라미터를 줄이고 컴팩트한 함수를 만드는 것에 도움을 준다.

def hello(name, postfix):
    print(f"Hello, {name}, {postfix}")
    return
hello("James", "sir")
>>> Hello, James, sir
# 위처럼 단순한 함수를 살펴보자
## sir 이라는 호칭을 사용하고 싶은데, 대부분 사용해야 하는 경우라면

def hello(name, postfix = "sir"):
    print(f"Hello, {name}, {postfix}")
    return
hello("James")
>>> Hello, James, sir
# 이처럼 호칭 기본값을 sir로 해준다면, 굳이 인자로 전달하지 않아도 된다. 편하다.
  • 기본 인수는 당연히 기본 인수가 없는 파라미터 뒤에 위치해야 한다.
  • 기본 인수로 가변객체는 피하면 좋다.

args와 kargs 사용하기

  • args : * 를 사용하면 리스트나 튜플 같은 iterator를 전달할 수 있다.
  • kargs : ** 를 사용하면 딕셔너리 같은 key, value 형식의 인자를 전달할 수 있다.
# args 활용
>>> def func(*args):
...     for i, val in enumerate(args):
...         print(f"Hello, {val}")
...     return
>>> func('James', 'Tom', 'Chris')
Hello, James
Hello, Tom
Hello, Chris

위 예시처럼 iterator 객체를 전달하지 않고도, 여러 인자를 iterator 처럼 활용할 수 있다.
kargs 또한 마찬가지 이다.
dict 딕셔너리 객체를 사용하지 않고, key-value 형태의 인자를 전달한다면 kargs에서 활용 가능하다.

map과 filter 대신 list comprehension

예전 파이썬에서는 map과 filter 등 한줄짜리 함수를 위한 기능을 활용했다고 한다.

# 리스트 값을 2배 증가시키기 위한 동작
>>> new = map(lambda n: n * 2, [1,2,3,4])
>>> list(new)
[2, 4, 6, 8]

# 홀수 객체만 남기기 위한 동작
>>> new = filter(lambda n: n % 2 == 1, [1,2,3,4])
>>> list(new)
[1, 3]

하지만 이제 그럴 필요가 없다.
리스트 컴프리헨션이 map, filter를 완벽하게 대체해주고 있으며, 심지어 보다 빠르다.

# 동일하게 동작하는 리스트 컴프리헨션
>>> new = [i * 2 for i in [1,2,3,4]]
>>> new
[2, 4, 6, 8]
>>> new = [i for i in [1,2,3,4] if i % 2 == 1]
>>> new
[1, 3]
반응형