파이썬에서 값 객체를 정의하는 좋은 방법에 대해 궁금합니다. 위키 피 디아 : "value object은 동일성이 동일성을 기반으로하지 않는 간단한 엔티티를 나타내는 작은 객체입니다. 즉, 두 값 객체가 동일한 값을 가질 때 동일하며 동일한 객체가 아니어도됩니다. 파이썬에서는 본질적으로 변하지 않는 것은 물론 __eq__
및 __hash__
메서드를 다시 정의하는 것을 의미합니다.Python에서 PyCharm 친화적 인 값 객체를 정의하는 방법은 무엇입니까?
표준 namedtuple
은 PyCharm과 같은 최신 Python IDE에서 잘 돌아 가지 않는 거의 완벽한 솔루션처럼 보입니다. IDE가 namedtuple
으로 정의 된 클래스에 대한 유용한 통찰력을 제공하지 않는다는 의미입니다. 그것은 가능하지만이 같은 트릭을 사용하여 같은 클래스에 문서화 문자열을 연결하려면 :
class Point2D(namedtuple("Point2D", "x y")):
"""Class for immutable value objects"""
pass
단순히 생성자 인자의 설명을 넣어 자신의 유형을 지정하는 곳이 없습니다. PyCharm은 Point2D
"constructor"에 대한 인수를 추측 할 수있을만큼 똑똑하지만 타입 상 현명합니다. ,
class Point2D(namedtuple("Point2D", "x y")):
"""Class for immutable value objects"""
def __new__(cls, x, y):
"""
:param x: X coordinate
:type x: float
:param y: Y coordinate
:type y: float
:rtype: Point2D
"""
return super(Point2D, cls).__new__(cls, x, y)
point = Point2D(1.0, 2.0)
PyCharm 새로운 객체를 구성 유형을 볼 수 있지만 수레는 그 point.x 및 point.y을 파악하지 않습니다
이 코드는 어떤 종류의 정보가 밀어 가지고 있지만, 그것은 매우 유용 아니다 그들의 오용을 감지하는 데 도움이되지는 않을 것입니다. 그리고 나는 또한 일상적으로 "마법"방법을 재정의한다는 생각을 싫어한다.
그래서 나는 것입니다 뭔가를 찾고 있어요 :- 일반 파이썬 클래스 또는 namedtuple
- 값의 의미 (평등, 해시, 불변성)
- 쉬운에 제공으로 정의 그냥 쉽게 IDE와 잘
이상적인 솔루션을 재생하는 방법 문서는 다음과 같이 수 :
class Point2D(ValueObject):
"""Class for immutable value objects"""
def __init__(self, x, y):
"""
:param x: X coordinate
:type x: float
:param y: Y coordinate
:type y: float
"""
super(Point2D, self).__init__(cls, x, y)
또는 그 :
class Point2D(object):
"""Class for immutable value objects"""
__metaclass__ = ValueObject
def __init__(self, x, y):
"""
:param x: X coordinate
:type x: float
:param y: Y coordinate
:type y: float
"""
pass
이 같은 있지만 성공하지 않고 뭔가를 찾기 위해 노력했다. 혼자서 구현하기 전에 도움을 요청하는 것이 현명 할 것이라고 생각했습니다.
업데이트 : user4815162342의 도움으로 나는 작동하는 것을 만들어 냈습니다. 코드는 다음과 같습니다.
class ValueObject(object):
__slots__ =()
def __repr__(self):
attrs = ' '.join('%s=%r' % (slot, getattr(self, slot)) for slot in self.__slots__)
return '<%s %s>' % (type(self).__name__, attrs)
def _vals(self):
return tuple(getattr(self, slot) for slot in self.__slots__)
def __eq__(self, other):
if not isinstance(other, ValueObject):
return NotImplemented
return self.__slots__ == other.__slots__ and self._vals() == other._vals()
def __ne__(self, other):
return not self == other
def __hash__(self):
return hash(self._vals())
def __getstate__(self):
"""
Required to pickle classes with __slots__
Must be consistent with __setstate__
"""
return self._vals()
def __setstate__(self, state):
"""
Required to unpickle classes with __slots__
Must be consistent with __getstate__
"""
for slot, value in zip(self.__slots__, state):
setattr(self, slot, value)
이상적인 해결책과는 거리가 멀습니다. 클래스 선언은 다음과 같습니다
class X(ValueObject):
__slots__ = "a", "b", "c"
def __init__(self, a, b, c):
"""
:param a:
:type a: int
:param b:
:type b: str
:param c:
:type c: unicode
"""
self.a = a
self.b = b
self.c = c
그것은 총 네 번 모든 속성을 나열 : __slots__
에서의 ctor 인수에 문서화 문자열과의 ctor 본문에. 지금까지 나는 그것을 덜 어색하게 만드는 방법을 모른다.
'namedtuple'은 튜플 인터페이스 (색인화, 압축 해제)와 속성 액세스를 모두 제공한다는 주된 목적을 가지고 있습니다. 'os.stat' 나'time.gmtime'과 같은 튜플을 반환하는 함수의 하위 호환성을 위해 개발되었습니다. 단순한 값 유형에 대해서는 최적의 선택이 아닐 수도 있습니다. – user4815162342
관련 유형 : * PyCharm은 Point2D "constructor"에 대한 인수를 추측 할만큼 똑똑하지만 형식이 잘못되었습니다. * 정적으로 입력 된 언어를 사용해야합니까? 파이썬에서는 IDE가 타입에 관해서 눈이 멀지는 않는다. – user4815162342
글쎄,'namedtuple'은 나에게 맞는 직업이다. 그것은 분명히 단순한 가치 객체이지만, 나는 그것과 함께 살 수 있습니다. 정적 유형 언어를 사용하는 것에 관해서는 할 수 있었으면합니다. 그러나 나는 손에 파이썬 프로젝트를 가지고 있으며 개발을보다 편하게 할 수있는 방법을 찾고 있습니다. 그리고 PyCharm은 이미 docstring을 사용하여 변수 유형을 추론하는 데 아주 능숙합니다. –