public interface IInterface
{
void show();
}
public class MyClass : IInterface
{
#region IInterface Members
public void show()
{
Console.WriteLine("Hello World!");
}
#endregion
}
이 C # 코드와 동등한 Python을 어떻게 구현합니까?
class IInterface(object):
def __init__(self):
pass
def show(self):
raise Exception("NotImplementedException")
class MyClass(IInterface):
def __init__(self):
IInterface.__init__(self)
def show(self):
print 'Hello World!'
이것이 좋은 생각입니까? 답변에 예를 들어주십시오.
답변
다른 여기에서 언급했듯이 :
파이썬에서는 인터페이스가 필요하지 않습니다. 파이썬에는 적절한 다중 상속과 덕 타이핑이 있기 때문에 자바에서 인터페이스가 있어야 하는 곳 은 파이썬에서 인터페이스를 가질 필요가 없습니다.
그러나 인터페이스에는 여전히 몇 가지 용도가 있습니다. 그중 일부는 Python 2.6에 도입 된 Pythons Abstract Base Classes로 덮여 있습니다. 인스턴스화 할 수 없지만 특정 인터페이스 또는 구현의 일부를 제공하는 기본 클래스를 만들려는 경우 유용합니다.
또 다른 사용법은 객체가 특정 인터페이스를 구현하도록 지정하려는 경우 서브 클래스를 사용하여 ABC를 사용할 수도 있습니다. 또 다른 방법은 zope.interface로, 정말 멋진 컴포넌트 프레임 워크 인 Zope Component Architecture의 일부인 모듈입니다. 여기서는 인터페이스에서 서브 클래스가 아니라 클래스 (또는 인스턴스)를 인터페이스 구현으로 표시합니다. 구성 요소 레지스트리에서 구성 요소를 조회하는 데에도 사용할 수 있습니다. 슈퍼 쿨!
답변
추상 기본 클래스에 abc 모듈을 사용하면 트릭을 수행하는 것 같습니다.
from abc import ABCMeta, abstractmethod
class IInterface:
__metaclass__ = ABCMeta
@classmethod
def version(self): return "1.0"
@abstractmethod
def show(self): raise NotImplementedError
class MyServer(IInterface):
def show(self):
print 'Hello, World 2!'
class MyBadServer(object):
def show(self):
print 'Damn you, world!'
class MyClient(object):
def __init__(self, server):
if not isinstance(server, IInterface): raise Exception('Bad interface')
if not IInterface.version() == '1.0': raise Exception('Bad revision')
self._server = server
def client_show(self):
self._server.show()
# This call will fail with an exception
try:
x = MyClient(MyBadServer)
except Exception as exc:
print 'Failed as it should!'
# This will pass with glory
MyClient(MyServer()).client_show()
답변
인터페이스 는 Python 2.7 및 Python 3.4+를 지원합니다.
인터페이스 를 설치 하려면
pip install python-interface
예제 코드 :
from interface import implements, Interface
class MyInterface(Interface):
def method1(self, x):
pass
def method2(self, x, y):
pass
class MyClass(implements(MyInterface)):
def method1(self, x):
return x * 2
def method2(self, x, y):
return x + y
답변
현대의 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 게시물에서 영감을 얻었 습니다 .)
답변
Python에 대한 타사 인터페이스 구현 ( Twisted 에서도 사용되는 Zope ‘s )이 있지만, 일반적으로 Python 코더는 “ABC (Abstract Base Class)”라는 더 풍부한 개념을 사용하는 것을 선호합니다. 구현 측면도있을 수 있습니다. ABC는 특히 Python 2.6 이상에서 잘 지원됩니다 . PEP를 참조하십시오 . 그러나 이전 버전의 Python에서도 일반적으로 “가는 길”로 간주 됩니다. 그들이 그 방법을 재정의하는 것이 더 좋습니다!-)NotImplementedError
답변
이와 같은 것 (파이썬이 없기 때문에 작동하지 않을 수 있음) :
class IInterface:
def show(self): raise NotImplementedError
class MyClass(IInterface):
def show(self): print "Hello World!"
답변
내 이해는 파이썬과 같은 동적 언어에서는 인터페이스가 필요하지 않다는 것입니다. Java (또는 추상 기본 클래스가있는 C ++)에서 인터페이스는 예를 들어 올바른 매개 변수를 전달하여 일련의 작업을 수행 할 수 있도록 보장하는 수단입니다.
예를 들어 옵저버 블과 옵저버 블이있는 경우 옵저버 블은 IObserver 인터페이스를 지원하는 객체를 구독하는 데 관심이 있으며 그 결과 notify
동작 이 있습니다. 이것은 컴파일 타임에 확인됩니다.
파이썬에서는 compile time
런타임에 메소드 조회가 수행 되지 않습니다 . 또한 __getattr __ () 또는 __getattribute __ () 매직 메서드를 사용하여 조회를 재정의 할 수 있습니다. 즉, notify
속성 에 액세스 할 때 호출 가능을 반환 할 수있는 모든 개체를 관찰자로서 전달할 수 있습니다 .
이것은 파이썬의 인터페이스 가 존재 한다는 결론에 이르게합니다. 실제로 사용되는 순간에 집행이 연기됩니다.