본문 바로가기

Python

몰랐던 Python의 숨은 고급 기능 14가지 – 실무에 바로 쓰는 예제와 함께

728x90
반응형

Python을 꽤 다룰 줄 아는 당신.
하지만 어느 날, 동료의 코드에서 처음 보는 문법이나 데코레이터, 이상하게 깔끔한 구조를 보고 이런 생각을 했을 수 있습니다.

“이게 어떻게 돌아가는 거지?”
“나도 저런 코드 짜고 싶은데…”

Python은 단순한 문법 덕분에 입문하기 쉬운 언어지만, 그만큼 실무에서 자주 쓰이지 않는 고급 기능들이 많습니다. 문제는 그 기능들이 정말 유용한데도 잘 알려져 있지 않다는 것이죠.

이 글에서는 Python을 더 깊이 이해하고, 실무 코드에 적용할 수 있는 고급 기능 14가지를 예제와 함께 소개합니다.
바로 써먹을 수 있는 핵심 기능만 모았으니, 읽는 동안 “이건 내 프로젝트에 꼭 써봐야겠다” 싶은 것들이 하나쯤은 있을 겁니다.

반응형

1. Typing Overloads – 조건에 따라 타입이 달라지는 함수 정의

여러 타입 조합을 사용하는 함수는 타입 힌트가 애매해지기 마련입니다.
이럴 때 @overload를 사용하면, 상황에 맞는 시그니처를 명확히 지정할 수 있습니다.

from typing import Literal, overload

@overload
def transform(data: str, mode: Literal["split"]) -> list[str]: ...
@overload
def transform(data: str, mode: Literal["upper"]) -> str: ...

def transform(data: str, mode: Literal["split", "upper"]) -> list[str] | str:
    return data.split() if mode == "split" else data.upper()

split_words = transform("hello world", "split")  # list[str]
upper_words = transform("hello world", "upper")  # str

2. 위치 전용 / 키워드 전용 인자

함수를 정의할 때 인자를 어떤 방식으로만 받을지 강제할 수 있습니다.

def foo(a, /, b, *, c):  # a는 위치 전용, c는 키워드 전용
    print(a, b, c)

foo(1, 2, c=3)  # ✅ OK
foo(a=1, b=2, c=3)  # ❌ a는 위치 전용
foo(1, 2, 3)  # ❌ c는 키워드 전용

3. Future Annotations – 타입 평가 지연시키기

Python에서 클래스 내부에서 자신을 타입으로 참조할 때 from __future__ import annotations를 쓰면 편합니다.

from __future__ import annotations

class Foo:
    def bar(self) -> Foo:  # 문자열 없이 사용 가능
        return self

4. Generics – 타입에 유연성을 주는 제네릭

Python 3.12에서는 더 간결한 제네릭 문법이 추가되었습니다.

class KVStore[K: str | int, V]:
    def __init__(self) -> None:
        self.store: dict[K, V] = {}

    def set(self, key: K, value: V) -> None:
        self.store[key] = value

kv = KVStore[str, int]()
kv.set("one", 1)

5. Protocols – duck typing으로 인터페이스 만들기

클래스 상속 없이도 특정 메서드만 구현하면 OK.

from typing import Protocol

class Quackable(Protocol):
    def quack(self) -> None: ...

class Duck:
    def quack(self): print("Quack!")

def run_quack(obj: Quackable):
    obj.quack()

run_quack(Duck())  # ✅ 작동함

6. Context Manager – with 블록 직접 만들기

컨텍스트 매니저를 제너레이터로 간단하게 만들 수 있습니다.

import contextlib

@contextlib.contextmanager
def retry():
    print("Entering")
    yield
    print("Exiting")

with retry():
    print("Inside context")

7. Structural Pattern Matching – 더 강력한 조건 분기

Python 3.10에서 도입된 match-case는 if-else보다 훨씬 직관적입니다.

point = (1, 2)

match point:
    case (0, 0): print("Origin")
    case (x, y): print(f"Point at ({x}, {y})")

8. slots – 메모리 최적화하기

인스턴스 속성이 많지 않은 경우 메모리를 줄일 수 있습니다.

class Person:
    __slots__ = ('name', 'age')
    def __init__(self, name, age):
        self.name = name
        self.age = age

9. Python 문법 꿀팁들 – 짧고 간결한 표현 모음

  • 왈러스 연산자 (:=): 값 할당과 조건 확인을 동시에
  • 연산자 체이닝: 직관적인 범위 조건
# Walrus Operator
if response := input("입력: "):
    print(f"입력값: {response}")

# Operator Chaining
x = 5
if 0 < x < 10:
    print("x는 0보다 크고 10보다 작다")

10. 고급 f-string 포맷팅

f-string은 단순한 출력 그 이상입니다.

progress = 0.874
print(f"진행률: {progress:.1%}")  # 진행률: 87.4%
print(f"{'제목':*^20}")  # ********제목********

11. @cache와 @lru_cache – 함수 결과 캐싱하기

재귀 함수 성능을 쉽게 높일 수 있습니다.

from functools import cache

@cache
def fib(n):
    return n if n < 2 else fib(n-1) + fib(n-2)

print(fib(10))  # 빠르게 계산

12. Futures – 비동기 작업 결과 다루기

concurrent.futures.Future는 JavaScript의 Promise처럼 작동합니다.

from concurrent.futures import Future

future = Future()
future.add_done_callback(lambda f: print(f"결과: {f.result()}"))
future.set_result("비동기 결과")

13. Proxy Property – 속성이면서 메서드처럼 동작하기

디스크립터를 활용하면 속성과 메서드를 넘나드는 API도 구현 가능합니다.

class ProxyProperty:
    def __init__(self, func):
        self.func = func

    def __get__(self, instance, _):
        self.instance = instance
        return self

    def __call__(self, *args, **kwargs):
        return self.func(self.instance, *args, **kwargs)

class Container:
    @ProxyProperty
    def value(self, val=5):
        return f"The value is: {val}"

c = Container()
print(c.value)     # The value is: 5
print(c.value(7))  # The value is: 7

14. 메타클래스 – 클래스 생성 자체를 커스터마이징

많이 쓰이지는 않지만, 클래스 속성 조작 등 특정 상황에 강력한 기능.

class DoubleAttrMeta(type):
    def __new__(cls, name, bases, namespace):
        new_namespace = {
            k: v * 2 if isinstance(v, int) else v for k, v in namespace.items()
        }
        return super().__new__(cls, name, bases, new_namespace)

class MyClass(metaclass=DoubleAttrMeta):
    x = 5
    y = 10

print(MyClass.x)  # 10
print(MyClass.y)  # 20
728x90

어떤 기능을 지금 써봐야 할까?

지금까지 소개한 14가지 고급 기능들은 다음과 같은 상황에서 큰 힘을 발휘합니다:

  • 타입 안정성과 자동완성 강화 → @overload, Generics, Protocols
  • 가독성과 유지보수성 향상 → pattern matching, f-string, 위치/키워드 전용 인자
  • 성능 최적화 → __slots__, @cache, 메타클래스
  • 비동기 로직 → Future 객체
  • 고급 API 설계 → Proxy Property, Context Manager

https://blog.edward-li.com/tech/advanced-python-features/

 

14 Advanced Python Features

Python is one of the most widely adopted programming languages in the world. Yet, because of it’s ease and simplicity to just “get something working”, it’s also one of the most underappreciated. If you search for Top 10 Advanced Python Tricks on Go

blog.edward-li.com

728x90
반응형