Python 인터페이스: ABC보다 프로토콜 선택

Feb 05 2023
새롭고 반짝이는 프로토콜을 선호하는 몇 가지 실용적인 이유 나는 지난 10년 동안 표준 Python 라이브러리 abc를 사용하여 인터페이스를 정의했습니다. 하지만 최근에는 상대적으로 새로운 Python 프로토콜이 훨씬 더 좋다는 것을 알게 되었습니다.

새롭고 반짝이는 프로토콜을 선호하는 몇 가지 실용적인 이유

아름다운 인터페이스는 미래에 성과를 거둘 것입니다 — Unsplash의 John Barkiple 신용

abc저는 지난 10년 동안 표준 Python 라이브러리를 사용하여 인터페이스를 정의했습니다. 하지만 최근에는 상대적으로 새로운 Python 프로토콜이 훨씬 더 좋다는 것을 알게 되었습니다 . 사람들은 두 기술의 용도를 찾습니다. 그러나 나는 당신이 배를 완전히 뛰어 넘고 전통적인 기술 대신 배를 사용하기 시작하도록 설득하고 싶습니다.

Python 인터페이스: 무엇을 사용할 수 있습니까?

Python은 언어 수준의 인터페이스가 없기 때문에 다른 대중적인 언어와 다소 다릅니다. 그러나 몇 가지 라이브러리 구현이 있습니다. 이 abc패키지는 아마도 가장 인기가 있을 것입니다.

from abc import ABC, abstractmethod

class Animal(ABC):
   @abstractmethod
   def eat(self, food) -> float:
       pass
   @abstractmethod
   def sleep(self, hours) -> float:
       pass

from zope.interface import Interface

class Animal(Interface):
   def eat(self, food) -> float:
       pass
   def sleep(self, hours) -> float:
       pass

마지막으로 다음과 같은 프로토콜이 있습니다.

from typing import Protocol

class Animal(Protocol):
   def eat(self, food) -> float:
       ...
   def sleep(self, hours) -> float:
       ...

무엇을 사용해야 합니까?

인터페이스 시스템은 코드베이스의 작은 부분으로 지역화되지 않는다는 점을 알아야 합니다. 하나만 가지고 가기로 선택한 후에는 어디에서나 볼 수 있고, 앞으로도 변경하기 어려울 것입니다. 따라서 사용자 지정 구현 또는 Zope. 설치, 버전, 지원 등 영원히 처리해야 하는 추가 종속성입니다. 예를 들어 우물 을 지원하려면 Mypy 플러그인을 설치해야 합니다 zope.interface. 또한 팀의 새로운 개발자는 이 사용자 지정 패키지를 모를 수 있으므로 이 패키지가 무엇이며 선택한 이유를 설명해야 합니다.

주요 전투는 abc와 사이에 발생합니다 Protocols. zope하지만 정말로 대 전투를 원한다면 이 상세 분석을Protocols 읽어보세요 .

먼저 정적 검사

내가 하려는 큰 가정은 정적 검사가 필수라는 것을 이미 확신하고 있다는 것입니다 . 실패한 코드를 실행하지 않을 것입니다 pylint/mypy. 두 체커 모두 똑같이 잘 지원 abc합니다 Protocols. 또한 둘 다 알고 필요한 경우 런타임 검사를 허용하십시오 abc.Protocols

둘 다 명시적 구문을 지원합니다.

첫째, 여전히 명시적으로 an abc 및 a 에서 상속할 수 있습니다 Protocol. Arjan 의 아주 좋은 비디오 (및 댓글) 의 많은 주장은 프로토콜로는 그렇게 할 수 없다는 오해를 중심으로 전개됩니다. 당신은 완전히 할 수 있습니다:

class Giraffe(Animal):
   ...

class Giraffe:  # no base class needed!
   def eat(self, food) -> float:
       return 0.
 
   def sleep(self, hours) -> float:
       return 1.

def feed_animal(animal: Animal):
    ... 

giraffe = Giraffe()
feed_animal(giraffe)

abc또한 " 가상 하위 클래스 " 개념을 통해 암시적 인터페이스를 지원합니다 . register그러나 모든 구현에 대해 다음을 호출해야 합니다 .

class Giraffe:  # no base class needed!
   def eat(self, food) -> float:
       return 0.

class Animal(ABC):
    ...

Animal.register(Giraffe)  # achieves the same as implicit Protocol

프로토콜을 사용하면 함수 (클래스뿐만 아니라) 에 대한 인터페이스를 정의할 수 있습니다 — 콜백 프로토콜 참조 . 별도의 게시물의 가치가 매우 멋진 기능입니다.

둘 다 기본 방법을 지원합니다(불행히도).

abc과 에는 큰 단점이 있습니다 Protocols. 현실 세계에서는 많은 사람들이 단일 코드베이스에서 작업합니다. 추상 기본 클래스는 때때로 기본 메서드 구현을 획득하는 경향이 있습니다. 다음과 같이 표시될 수 있습니다.

class Animal(Protocol):  # the same holds for Animal(ABC):
   def eat(self, food) -> float:
       ...  # this is still abstract
 
   def sleep(self, hours) -> float:
       return 3.

프로토콜이 더 짧음

마지막으로 인터페이스를 정의하는 데 필요한 코드 줄 수를 계산할 수 있습니다. 를 사용하면 모든 메서드에 대한 데코레이터가 abc있어야 합니다 . abstractmethod그러나 런타임 검사가 없는 프로토콜을 사용하면 데코레이터를 전혀 사용할 필요가 없습니다. 그래서 여기에서 프로토콜이 승리합니다.

결론

점수를 합산해 보겠습니다.

바라건대, 나는 이 분석에서 큰 것을 놓치고 있지 않습니다. 결과를 보면 "Protocols" 팀이 이겼고, 아마도 그것을 사용하기 시작해야 할 것입니다!

이 글이 도움이 되셨다면 박수 한 번 부탁드립니다. 읽어 주셔서 감사합니다!

LinkedIn 또는 Twitter 에서 저를 찾을 수 있습니다 .

자원

  • 오리 타이핑 위키
  • Taylor Manderson의 좋은 오리 타이핑 튜토리얼
  • Zope와 Glyph의 프로토콜 간의 유사한 비교
  • Arjan의 ABC 대 프로토콜 비교
  • 콜백 프로토콜이 있는 기능적 인터페이스

레벨업 코딩

우리 커뮤니티의 일원이 되어 주셔서 감사합니다! 가기 전에:

  • 이야기에 박수치고 작가 팔로우
  • 레벨업 코딩 출판물 에서 더 많은 콘텐츠 보기
  • 팔로우: 트위터 | 링크드인 | 뉴스 레터