현대의 Python 3에서는 추상 기본 클래스로 인터페이스를 구현하는 것이 훨씬 간단하며 플러그인 확장을위한 인터페이스 계약의 목적으로 사용됩니다.
인터페이스 / 추상 기본 클래스를 만듭니다.
from abc import ABC, abstractmethod
class AccountingSystem(ABC):
@abstractmethod
def create_purchase_invoice(self, purchase):
pass
@abstractmethod
def create_sale_invoice(self, sale):
log.debug('Creating sale invoice', sale)
일반 서브 클래스를 작성하고 모든 추상 메소드를 대체하십시오.
class GizmoAccountingSystem(AccountingSystem):
def create_purchase_invoice(self, purchase):
submit_to_gizmo_purchase_service(purchase)
def create_sale_invoice(self, sale):
super().create_sale_invoice(sale)
submit_to_gizmo_sale_service(sale)
위와 같이 서브 클래스에서 명시 적으로 create_sale_invoice()
호출하여에서와 같이 추상 메소드에서 공통 구현을 선택적으로 가질 수 있습니다 super()
.
모든 추상 메소드를 구현하지 않는 서브 클래스 인스턴스화가 실패합니다.
class IncompleteAccountingSystem(AccountingSystem):
pass
>>> accounting = IncompleteAccountingSystem()
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
TypeError: Can't instantiate abstract class IncompleteAccountingSystem with abstract methods
create_purchase_invoice, create_sale_invoice
해당 주석을와 결합하여 추상 속성, 정적 및 클래스 메서드를 가질 수도 있습니다 @abstractmethod
.
추상 기본 클래스는 플러그인 기반 시스템을 구현하는 데 적합합니다. 클래스의 모든 가져온 서브 클래스는를 통해 액세스 할 수 __subclasses__()
있으므로 플러그인 디렉토리에서 모든 클래스를로드 importlib.import_module()
하고 기본 클래스를 서브 클래스로로드하는 경우 클래스를 통해 직접 액세스 __subclasses__()
할 수 있으며 모든 클래스 에 대해 인터페이스 계약이 시행되도록 할 수 있습니다. 인스턴스화하는 동안.
AccountingSystem
위 예제에 대한 플러그인 로딩 구현은 다음과 같습니다 .
...
from importlib import import_module
class AccountingSystem(ABC):
...
_instance = None
@classmethod
def instance(cls):
if not cls._instance:
module_name = settings.ACCOUNTING_SYSTEM_MODULE_NAME
import_module(module_name)
subclasses = cls.__subclasses__()
if len(subclasses) > 1:
raise InvalidAccountingSystemError('More than one '
f'accounting module: {subclasses}')
if not subclasses or module_name not in str(subclasses[0]):
raise InvalidAccountingSystemError('Accounting module '
f'{module_name} does not exist or does not '
'subclass AccountingSystem')
cls._instance = subclasses[0]()
return cls._instance
그런 다음 AccountingSystem
클래스를 통해 계정 시스템 플러그인 오브젝트에 액세스 할 수 있습니다 .
>>> accountingsystem = AccountingSystem.instance()
( 이 PyMOTW-3 게시물에서 영감을 얻었 습니다 .)