Python의 동적인 특성과 덕 타이핑 지원은 유연성으로 인해 오랫동안 칭찬을 받아 왔습니다. 그러나 코드베이스가 더 커지고 복잡해짐에 따라 정적 유형 검사의 이점이 점점 더 분명해집니다. 하지만 덕 타이핑의 유연성과 정적 유형 검사의 안전성을 어떻게 조화시킬 수 있을까요? Python의 프로토콜 클래스를 입력하세요.
이 튜토리얼에서 배울 내용은 다음과 같습니다.
오리 타이핑은 개체의 유형이나 클래스가 개체가 정의하는 메서드보다 덜 중요한 프로그래밍 개념입니다. '오리처럼 보이고, 오리처럼 헤엄치고, 오리처럼 꽥꽥거린다면 아마도 오리일 것이다'라는 생각에서 출발한 것입니다.
Python에서는 덕 타이핑이 완벽하게 지원됩니다. 예:
class Duck: def quack(self): print("Quack!") class Person: def quack(self): print("I'm imitating a duck!") def make_it_quack(thing): # Note: No type hint here thing.quack() duck = Duck() person = Person() make_it_quack(duck) # Output: Quack! make_it_quack(person) # Output: I'm imitating a duck!
이 예에서 make_it_quack은 사물의 유형에 관심이 없습니다. 그 물건에 돌팔이 방법이 있는지에만 관심이 있습니다. thing 매개변수에 대한 유형 힌트가 없다는 점에 유의하세요. 이는 duck 유형의 코드에서 일반적이지만 더 큰 코드베이스에서는 문제를 일으킬 수 있습니다.
덕 타이핑은 여러 가지 장점을 제공합니다.
그러나 몇 가지 단점도 있습니다.
이러한 문제를 해결하는 한 가지 접근 방식은 ABC(추상 기본 클래스)를 사용하는 것입니다. 예는 다음과 같습니다.
from abc import ABC, abstractmethod class Quacker(ABC): @abstractmethod def quack(self): pass class Duck(Quacker): def quack(self): print("Quack!") class Person(Quacker): def quack(self): print("I'm imitating a duck!") def make_it_quack(thing: Quacker): thing.quack() duck = Duck() person = Person() make_it_quack(duck) make_it_quack(person)
이 접근 방식은 더 나은 유형 검사와 더 명확한 인터페이스를 제공하지만 다음과 같은 단점도 있습니다.
Python 3.8에는 상속 없이 인터페이스를 정의할 수 있는 프로토콜 클래스가 도입되었습니다. 사용 방법은 다음과 같습니다.
from typing import Protocol class Quacker(Protocol): def quack(self):... class Duck: def quack(self): print("Quack!") class Person: def quack(self): print("I'm imitating a duck!") def make_it_quack(thing: Quacker): thing.quack() duck = Duck() person = Person() make_it_quack(duck) make_it_quack(person)
이를 분석해 보겠습니다.
이러한 접근 방식은 다음과 같은 몇 가지 이점을 제공합니다.
다음은 도메인 클래스(원, 직사각형)를 평면으로 유지하면서 프로토콜이 필요한 만큼 복잡할 수 있는 방법(모양)을 보여주는 더 복잡한 예입니다.
from typing import Protocol, List class Drawable(Protocol): def draw(self): ... class Resizable(Protocol): def resize(self, factor: float): ... class Shape(Drawable, Resizable, Protocol): pass def process_shapes(shapes: List[Shape]): for shape in shapes: shape.draw() shape.resize(2.0) # Example usage class Circle: def draw(self): print("Drawing a circle") def resize(self, factor: float): print(f"Resizing circle by factor {factor}") class Rectangle: def draw(self): print("Drawing a rectangle") def resize(self, factor: float): print(f"Resizing rectangle by factor {factor}") # This works with any class that has draw and resize methods, # regardless of its actual type or inheritance shapes: List[Shape] = [Circle(), Rectangle()] process_shapes(shapes)
이 예에서 Circle 및 Rectangle은 Shape 또는 다른 클래스에서 상속되지 않습니다. 그들은 단순히 필요한 메소드(그리기 및 크기 조정)를 구현합니다. process_shapes 함수는 Shape 프로토콜 덕분에 이러한 메소드를 가진 모든 객체와 함께 작동할 수 있습니다.
Python의 프로토콜은 덕 유형의 코드에 정적 유형을 적용하는 강력한 방법을 제공합니다. 이를 통해 상속을 요구하지 않고 유형 시스템에서 인터페이스를 지정할 수 있으며 덕 타이핑의 유연성을 유지하면서 정적 유형 검사의 이점을 추가할 수 있습니다.
프로토콜을 사용하면 다음이 가능합니다.
Python의 프로토콜 및 유형 힌트에 대해 자세히 알아보려면 타이핑 모듈에 대한 공식 Python 문서를 확인하거나 mypy와 같은 고급 정적 유형 검사 도구를 살펴보세요.
즐거운 코딩을 즐기시고, 여러분의 오리가 항상 유형 안전을 지키길 바랍니다!
여기에서 내 뉴스레터를 포함한 더 많은 콘텐츠를 찾을 수 있습니다
위 내용은 오리 타이핑과 유형 힌트의 만남: Python에서 프로토콜 사용의 상세 내용입니다. 자세한 내용은 PHP 중국어 웹사이트의 기타 관련 기사를 참조하세요!