sourcecode

raise Not Implemented Error'를 사용해야 하는 경우

codebag 2023. 7. 12. 23:46
반응형

raise Not Implemented Error'를 사용해야 하는 경우

자신과 팀원들에게 수업을 올바르게 이행하도록 상기시키기 위한 것입니까?다음과 같은 추상적인 수업을 완전히 사용하지는 못합니다.

class RectangularRoom(object):
    def __init__(self, width, height):
        raise NotImplementedError

    def cleanTileAtPosition(self, pos):
        raise NotImplementedError

    def isTileCleaned(self, m, n):
        raise NotImplementedError

문서에 명시되어 있듯이,

사용자 정의 기본 클래스에서 추상 메서드는 메서드를 재정의하기 위해 파생 클래스가 필요하거나 클래스가 개발되는 동안 실제 구현을 계속 추가해야 함을 나타내는 경우 이 예외를 제기해야 합니다.

클래스에 주,▁methods▁that▁is▁note▁you▁it▁anyhow,▁for▁case▁▁aication▁use▁classes▁use▁like▁of▁▁ind'▁can▁although▁the▁the▁you다▁stated니습있▁main▁that▁like수d할▁of용ication사▁abstract▁inherited대로는▁inded▁be원▁on하▁implement같▁should음이다이과류,만가TODO마커

Uriel이 말했듯이, 이것은 추상 클래스의 메서드를 의미하며, 하위 클래스에서 구현되어야 하지만 TODO를 나타내는 데도 사용될 수 있습니다.

첫 번째 사용 사례에 대한 대안이 있습니다.추상 기본 클래스입니다.추상 클래스를 만드는 데 도움이 됩니다.

다음은 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, ...):
        ...

이제인화할수다있니습스턴스iate를 인스턴스화할 수 .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당신이 그것을 부를 때.

  • 당신은 당신이 원했던 오버라이드 기능을 얻을 수 있습니까?절대 아닙니다.
  • 아이즈None유한출 ? 누가 누가 알겠어요.
  • 의도된 행동입니까?거의 확실하지 않습니다.
  • 오류가 발생합니까?사정에 따라 다르겠지.

raise NotImplmentedError 명령을 실행할 때까지 실행하려고 하면 예외가 발생하므로 이 명령을 실행하도록 강제합니다.이렇게 하면 많은 무음 오류가 제거됩니다.그것은 왜 맨 예외가 거의 좋은 생각이 아닌지와 비슷합니다. 왜냐하면 사람들은 실수를 하고 이것은 그들이 양탄자에 휩쓸리지 않도록 하기 때문입니다.

참고: 다른 답변에서 언급한 것처럼 추상 기본 클래스를 사용하는 것이 더 낫습니다. 그러면 오류가 미리 로드되고 오류를 구현할 때까지 프로그램이 실행되지 않습니다(Not ImplementedError의 경우 실제로 호출된 경우에만 예외가 발생합니다).

사람은 또한 할 수 있습니다.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

공유 동사

그런 다음 모듈별 명령 동사의 상당 부분이 공유되므로 인터페이스의 논리도 공유된다는 것을 깨달았습니다.여기 여러 대상 모듈을 고려할 때 의미가 자기 설명이 되는 세 가지 다른 동사가 있습니다.

get(channel):

  • relay: 릴레이의 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 모듈에서는 이 기능이 작동하지 않습니다.

맞다니를 하지 않습니다. 구현하지 않음setADC 개체를 인스턴스화하려고 하면 Python이 아래 오류를 발생시키므로 이 옵션은 아닙니다.

TypeError: Can't instantiate abstract class 'ADC' with abstract methods 'set'

그래서 당신은 무언가를 실행해야 합니다, 왜냐하면 우리가 만들었기 때문입니다.set 개의 다른 모듈에 의해 공유되는 시행 동사(일명 '@httpsmethod'), 그러나 동시에 다음과 같은 것을 구현해서는 안 됩니다.set는 이 특정 모듈에 적합하지 않습니다.

복구에 대한 구현되지 않은 오류

다음과 같이 ADC 클래스를 완료합니다.

class ADC(Generic): # ...continued

    def set(self, channel):
        raise NotImplementedError("Can't use 'set' on an ADC!")

당신은 동시에 세 가지 매우 좋은 일을 하고 있습니다.

  1. 사용자가 이 모듈에 대해 구현되지 않은(그리고 구현되지 않아야 함!) 명령('set')을 잘못 실행하지 않도록 보호하고 있습니다.
  2. 당신은 그들에게 문제가 무엇인지 명시적으로 말하고 있습니다(왜 이것이 중요한지에 대한 '베어 예외'에 대한 Temporal Wolf의 링크 참조).
  3. 당신은 시행된 동사가 의미를 갖는 다른 모든 모듈의 구현을 보호하고 있습니다.즉, 이러한 동사가 의미를 갖는 모듈이 이러한 방법을 구현하고 다른 임시 이름이 아닌 정확한 동사를 사용하여 구현하도록 보장합니다.

다음을 사용할 수 있습니다.@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

언급URL : https://stackoverflow.com/questions/44315961/when-to-use-raise-notimplementederror

반응형