자신과 팀이 수업을 올바르게 수행하도록 상기시키는 것입니까? 다음과 같은 추상 클래스를 완전히 사용하지 못했습니다.
class RectangularRoom(object):
def __init__(self, width, height):
raise NotImplementedError
def cleanTileAtPosition(self, pos):
raise NotImplementedError
def isTileCleaned(self, m, n):
raise NotImplementedError
답변
문서에서 [docs] ,
사용자 정의 기본 클래스에서 추상 메서드는 메서드를 재정의하기 위해 파생 클래스가 필요하거나 클래스가 개발되는 동안 실제 구현을 추가해야 함을 나타 내기 위해이 예외를 발생시켜야합니다.
이 오류는 상속 된 클래스에서 구현되어야하는 추상 메서드를 나타내는 주요 사용 사례이지만 TODO
마커 표시를 위해 원하는대로 사용할 수 있습니다 .
답변
으로 우리엘은 말한다 , 그것은 자식 클래스에서 구현해야하는 추상 클래스의 메소드에 대한 의미하지만,뿐만 아니라 TODO를 표시하는 데 사용할 수 있습니다.
첫 번째 사용 사례에 대한 대안이 있습니다 : Abstract Base Classes . 그것들은 추상 클래스를 만드는 데 도움이됩니다.
다음은 Python 3 예제입니다.
class C(abc.ABC):
@abc.abstractmethod
def my_abstract_method(self, ...):
...
인스턴스화 할 때 추상 C
이기 때문에 오류가 발생 my_abstract_method
합니다. 하위 클래스에서 구현해야합니다.
TypeError: Can't instantiate abstract class C with abstract methods my_abstract_method
하위 클래스를 C
만들고 my_abstract_method
.
class D(C):
def my_abstract_method(self, ...):
...
이제 D
.
C.my_abstract_method
비어 있지 않아도됩니다. 를 D
사용하여 호출 할 수 있습니다 super()
.
이것의 장점은 메서드 호출 시간이 아니라 인스턴스화 시간에 NotImplementedError
명시 Exception
적을 얻는다는 것입니다.
답변
대신 다음과 같은 경우 고려하십시오.
class RectangularRoom(object):
def __init__(self, width, height):
pass
def cleanTileAtPosition(self, pos):
pass
def isTileCleaned(self, m, n):
pass
그리고 당신은 하위 클래스를 만들고 isTileCleaned()
그것을 isTileCLeaned()
. 그런 다음 코드에서 None
호출 하면 a가 표시 됩니다.
- 원하는 재정의 된 기능을 얻을 수 있습니까? 절대 아니다.
- 가
None
유효 출력은? 누가 알아. - 의도 된 행동입니까? 거의 확실하지 않습니다.
- 오류가 발생합니까? 때에 따라 다르지.
raise NotImplmentedError
힘 은 당신이 그것을 구현하는 것입니다 당신이 이렇게까지 그것을 실행하려고하면 예외를 throw합니다. 이것은 많은 침묵 오류를 제거합니다. 맨손을 제외하고는 거의 좋은 생각이 아닌 이유와 비슷합니다 . 사람들은 실수를해서 깔개 아래로 휩쓸 리지 않도록하기 때문입니다.
참고 : 다른 답변에서 언급했듯이 추상 기본 클래스를 사용하는 것이 더 낫습니다. 그러면 오류가 프런트로드되고 프로그램이 구현 될 때까지 프로그램이 실행되지 않기 때문입니다 (NotImplementedError를 사용하면 실제로 호출되는 경우에만 예외가 발생합니다).
답변
-decorated 기본 클래스 메서드 의 자식 메서드 raise NotImplementedError()
내부 에서 수행 할 수도 있습니다 @abstractmethod
.
측정 모듈 (물리적 장치) 제품군에 대한 제어 스크립트를 작성한다고 상상해보십시오. 각 모듈의 기능은 좁게 정의되어 하나의 전용 기능 만 구현합니다. 하나는 릴레이 어레이, 다른 하나는 다중 채널 DAC 또는 ADC, 다른 하나는 전류계 등일 수 있습니다.
사용중인 대부분의 저수준 명령은 모듈간에 공유되어 ID 번호를 읽거나 명령을 보냅니다. 이 시점에서 우리가 가진 것을 보자 :
기본 클래스
from abc import ABC, abstractmethod #< we'll make use of these later
class Generic(ABC):
''' Base class for all measurement modules. '''
# Shared functions
def __init__(self):
# do what you must...
def _read_ID(self):
# same for all the modules
def _send_command(self, value):
# same for all the modules
공유 동사
그런 다음 모듈 별 명령 동사의 상당 부분과 그에 따른 인터페이스의 논리도 공유된다는 것을 알게됩니다. 다음은 여러 대상 모듈을 고려할 때 의미가 자명 한 3 가지 동사입니다.
-
get(channel)
-
릴레이 : 릴레이 의 on / off 상태를 가져옵니다.
channel
-
DAC : 얻가 출력 전압에를
channel
-
ADC : 얻가 입력 전압에를
channel
-
enable(channel)
-
릴레이 : 릴레이 사용 활성화
channel
-
DAC : 출력 채널 사용 활성화
channel
-
ADC : 입력 채널 사용 활성화
channel
-
set(channel)
-
릴레이 : 릴레이
channel
켜기 / 끄기 설정 -
DAC : 설정된 출력 전압 온
channel
-
ADC : 음 … 논리적으로 떠오르는 것은 없습니다 .
공유 동사가 강제 동사가 됨
위의 동사가 각 모듈에 대해 그 의미가 분명하다는 것을 알기 때문에 모듈 전체에서 공유되는 강력한 사례가 있다고 주장합니다. 다음 Generic
과 같이 기본 클래스를 계속 작성합니다 .
class Generic(ABC): # ...continued
@abstractmethod
def get(self, channel):
pass
@abstractmethod
def enable(self, channel):
pass
@abstractmethod
def set(self, channel):
pass
하위 클래스
이제 우리는 서브 클래스가 모두 이러한 메서드를 정의해야한다는 것을 알고 있습니다. ADC 모듈의 모습을 살펴 보겠습니다.
class ADC(Generic):
def __init__(self):
super().__init__() #< applies to all modules
# more init code specific to the ADC module
def get(self, channel):
# returns the input voltage measured on the given 'channel'
def enable(self, channel):
# enables accessing the given 'channel'
이제 궁금 할 것입니다.
그러나 이것은 위에서 본 것처럼 ADC 모듈 에서는 작동하지 않습니다
set
.
맞습니다 : 구현 set
하지 않는 것은 Python이 ADC 개체를 인스턴스화하려고 할 때 아래 오류를 발생시키기 때문에 옵션이 아닙니다.
TypeError: Can't instantiate abstract class 'ADC' with abstract methods 'set'
따라서 다른 두 모듈에서 공유 set
하는 강제 동사 ( ‘@abstractmethod’라고도 함)를 만들었 기 때문에 무언가를 구현해야 하지만 동시에이 set
특정 모듈에 대해 의미가없는 것은 구현
하지 않아야합니다.
구조에 NotImplementedError
다음과 같이 ADC 클래스를 완료하면 :
class ADC(Generic): # ...continued
def set(self, channel):
raise NotImplementedError("Can't use 'set' on an ADC!")
한 번에 세 가지 좋은 일을하고 있습니다.
- 이 모듈에 대해 구현되어서는 안되는 명령 ( ‘set’)을 잘못 실행하지 못하도록 사용자를 보호하고 있습니다.
- 문제가 무엇인지 명시 적으로 말하고 있습니다 (이것이 중요한 이유는 ‘베어 예외’에 대한 TemporalWolf의 링크 참조).
- 강제 동사
가 의미가 있는 다른 모든 모듈의 구현을 보호하고 있습니다. 즉, 이러한 동사 가 의미가 있는 모듈 이 이러한 메서드를 구현 하고 다른 임시 이름이 아닌 이 동사를 정확히 사용하여 수행하는지 확인 합니다.
답변
@property
데코레이터 를 사용하고 싶을 수도 있습니다 .
>>> class Foo():
... @property
... def todo(self):
... raise NotImplementedError("To be implemented")
...
>>> f = Foo()
>>> f.todo
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
File "<stdin>", line 4, in todo
NotImplementedError: To be implemented