Python의 추상 속성
Python에서 추상 속성을 가진 다음 Scala 코드를 구현하는 가장 짧고 우아한 방법은 무엇입니까?
abstract class Controller {
val path: String
}
하위 클래스의Controller는 Scala 컴파일러에 의해 "경로"를 정의하도록 강제됩니다.하위 클래스는 다음과 같습니다.
class MyController extends Controller {
override val path = "/home"
}
파이썬 3.3+
from abc import ABCMeta, abstractmethod
class A(metaclass=ABCMeta):
def __init__(self):
# ...
pass
@property
@abstractmethod
def a(self):
pass
@abstractmethod
def b(self):
pass
class B(A):
a = 1
def b(self):
pass
신고 실패a아니면b파생 계급에서B올릴 것입니다TypeError예를 들어:
TypeError: 추상 클래스를 인스턴스화할 수 없습니다.B추상적인 방법으로a
파이썬 2.7
이를 위한 @abstract property decorator가 있습니다.
from abc import ABCMeta, abstractmethod, abstractproperty
class A:
__metaclass__ = ABCMeta
def __init__(self):
# ...
pass
@abstractproperty
def a(self):
pass
@abstractmethod
def b(self):
pass
class B(A):
a = 1
def b(self):
pass
Python에는 이에 대한 기본 제공 예외가 있지만 런타임까지 예외가 발생하지 않습니다.
class Base(object):
@property
def path(self):
raise NotImplementedError
class SubClass(Base):
path = 'blah'
python은 원래 이 질문을 받은 이후로 추상적인 수업을 구현하는 방법을 바꾸었습니다.저는 abc를 사용하는 약간 다른 접근법을 사용해왔습니다.파이썬 3.6의 ABC 형식주의.여기서는 상수를 각 하위 클래스에서 정의해야 하는 속성으로 정의합니다.
from abc import ABC, abstractmethod
class Base(ABC):
@classmethod
@property
@abstractmethod
def CONSTANT(cls):
raise NotImplementedError
def print_constant(self):
print(type(self).CONSTANT)
class Derived(Base):
CONSTANT = 42
이것은 유도된 클래스가 상수를 정의하도록 강제합니다. 그렇지 않으면 aTypeError하위 클래스를 인스턴스화하려고 하면 예외가 발생합니다.추상 클래스에 구현된 함수에 대해 상수를 사용하려면 다음과 같이 하위 클래스 상수에 액세스해야 합니다.type(self).CONSTANT만이 아니라CONSTANT, 값이 기본 클래스에서 정의되지 않았기 때문입니다.
이것을 구현하기 위한 다른 방법들이 있지만, 저는 이 구문이 독자들에게 가장 쉽고 명확하게 보이기 때문에 좋아합니다.
이전의 답변들은 모두 유용한 점들을 감동시켰지만, 나는 수용된 답변이 질문에 직접적으로 답하지 못한다고 생각합니다. 왜냐하면
- 질문은 추상적 수업에서 실행을 요구하지만 수용된 대답은 추상적 형식주의를 따르지 않습니다.
- 문제는 이행을 강제할 것을 요구합니다.다음과 같은 경우 서브클래스가 인스턴스화될 때 런타임 오류가 발생하기 때문에 이 답변에서 강제성이 더 엄격하다고 주장합니다.
CONSTANT정의되지 않았습니다.승인된 답변은 개체를 인스턴스화할 수 있도록 허용하고 다음과 같은 경우에만 오류를 발생시킵니다.CONSTANT에 액세스하기 때문에 시행이 덜 엄격해집니다.
이것은 원래의 답변을 잘못하기 위함이 아닙니다.추상 클래스 구문에 대한 주요 변경 사항은 게시된 이후에 발생했으며, 이 경우 더 빠르고 기능적인 구현이 가능합니다.
Python 3.6+에서는 해당 속성에 대한 값을 제공하지 않고 추상 클래스(또는 변수)의 속성에 주석을 달 수 있습니다.
from abc import ABC
class Controller(ABC):
path: str
class MyController(Controller):
def __init__(self, path: str):
self.path = path
이것은 속성이 추상적인 것이 분명한 매우 깨끗한 코드를 만들어 줍니다.
하위 클래스에서 구현을 제공하지 않는 경우 정의 시점에서 예외가 발생하지 않습니다..AttributeError정의되지 않은 속성에 액세스하려고 하면 예외가 발생합니다.
abc에서 속성을 만들 수 있습니다.속성을 덮어쓰지 않고 사용할 경우 런타임에 의도를 나타내는 명확한 오류가 표시되도록 하는 등의 값을 가지는 ABC 추상 기본 클래스.
다음 코드는 PEP 484 유형 힌트를 사용하여 PyCharm이 정확하게 유형을 정적으로 분석할 수 있도록 도와줍니다.path속성도 마찬가지입니다.
from abc import ABC
class Controller(ABC):
path: str = NotImplemented
class MyController(Controller):
path = "/home"
Python 3.3+의 경우 우아한 솔루션이 있습니다.
from abc import ABC, abstractmethod
class BaseController(ABC):
@property
@abstractmethod
def path(self) -> str:
...
class Controller(BaseController):
path = "/home"
# Instead of an elipsis, you can add a docstring for clarity
class AnotherBaseController(ABC):
@property
@abstractmethod
def path(self) -> str:
"""
:return: the url path of this controller
"""
이미 몇 가지 훌륭한 답변이 나왔지만, 그럼에도 불구하고 이 답변이 가치를 더할 것이라고 생각했습니다.이 접근 방식에는 두 가지 장점이 있습니다.
...추상적인 방법으로 몸이 더 좋습니다.pass.와는 달리pass,...작업이 없음을 암시합니다.pass실제 구현의 부재를 의미할 뿐입니다....던지는 것보다 더 추천합니다.NotImplementedError(...)가 나타납니다 이렇게 하면 서브클래스에서 추상 필드 구현이 누락된 경우 매우 상세한 오류가 자동으로 나타납니다.그에 반해서,NotImplementedError그 자체로는 구현이 누락된 이유를 알 수 없습니다.게다가 실제로 키우려면 수작업이 필요합니다.
Python 3.6부터는 사용할 수 있습니다.__init_subclass__초기화 시 하위 클래스의 클래스 변수를 확인하는 방법:
from abc import ABC
class A(ABC):
@classmethod
def __init_subclass__(cls):
required_class_variables = [
'foo',
'bar',
]
for var in required_class_variables:
if not hasattr(cls, var):
raise NotImplementedError(
f'Class {cls} lacks required `{var}` class attribute'
)
이렇게 하면 결측 클래스 변수가 정의되지 않은 경우 하위 클래스 초기화 시 오류가 발생하므로 결측 클래스 변수에 액세스할 때까지 기다릴 필요가 없습니다.
모든 장식가들이 그렇게 많이 자리 잡지 않도록 @James 답변을 약간 수정했습니다.이러한 추상 속성을 여러 개 정의할 경우 다음과 같이 편리합니다.
from abc import ABC, abstractmethod
def abstractproperty(func):
return property(classmethod(abstractmethod(func)))
class Base(ABC):
@abstractproperty
def CONSTANT(cls): ...
def print_constant(self):
print(type(self).CONSTANT)
class Derived(Base):
CONSTANT = 42
class BadDerived(Base):
BAD_CONSTANT = 42
Derived() # -> Fine
BadDerived() # -> Error
Python 3.6 구현은 다음과 같습니다.
In [20]: class X:
...: def __init_subclass__(cls):
...: if not hasattr(cls, 'required'):
...: raise NotImplementedError
In [21]: class Y(X):
...: required = 5
...:
In [22]: Y()
Out[22]: <__main__.Y at 0x7f08408c9a20>
당신의 기본 클래스는 A를 구현할 수 있습니다.__new__클래스 속성을 확인하는 메서드:
class Controller(object):
def __new__(cls, *args, **kargs):
if not hasattr(cls,'path'):
raise NotImplementedError("'Controller' subclasses should have a 'path' attribute")
return object.__new__(cls)
class C1(Controller):
path = 42
class C2(Controller):
pass
c1 = C1()
# ok
c2 = C2()
# NotImplementedError: 'Controller' subclasses should have a 'path' attribute
이렇게 하면 인스턴스화 시 오류가 발생합니다.
Bastien Leonard의 답변은 추상적 기본 클래스 모듈을 언급하고 Brendan Abel의 답변은 구현되지 않은 속성이 오류를 제기하는 것을 다루고 있습니다.클래스가 모듈 외부에 구현되지 않도록 하려면 기본 이름 앞에 모듈의 개인(즉, 가져오지 않음)을 나타내는 밑줄을 붙이면 됩니다.
예.
class _Controller(object):
path = '' # There are better ways to declare attributes - see other answers
class MyController(_Controller):
path = '/Home'class AbstractStuff:
@property
@abc.abstractmethod
def some_property(self):
pass
.3 abc.abstractproperty감가상각된 것 같습니다.
abc(추상 베이스 클래스) 모듈 보기: http://docs.python.org/library/abc.html
하지만 가장 간단하고 일반적인 해결책은 기본 클래스의 인스턴스가 생성되거나 해당 속성에 액세스할 때 예외를 제기하는 것입니다.
언급URL : https://stackoverflow.com/questions/2736255/abstract-attributes-in-python
'programing' 카테고리의 다른 글
| RxJS - 오류가 발생하면 관측 가능이 완료되지 않습니다. (0) | 2023.10.27 |
|---|---|
| 시작 작업의 스크립트 블록에 제기된 예외를 캡처하는 방법은? (0) | 2023.10.27 |
| PHP 준비문 SQL with where 값 (0) | 2023.10.27 |
| MySQL에서 grave accent(일명 백틱) 인용 문자의 의미는 무엇입니까? (0) | 2023.10.27 |
| jquery ajax json과 함께 양식 데이터 전송 (0) | 2023.10.27 |