적어도 다섯 가지 방법이 있습니다. 선호하는 방법은 사용 사례에 따라 다릅니다.
옵션 1 : 간단히 asdict()방법을 추가합니다 .
문제 설명을 바탕으로 asdict다른 답변에서 제안한 작업 방법을 매우 많이 고려할 것입니다. 이것은 당신의 객체가 실제로 컬렉션의 많은 것 같지 않기 때문입니다.
class Wharrgarbl(object):
...
def asdict(self):
return {'a': self.a, 'b': self.b, 'c': self.c}
아래의 다른 옵션을 사용하면 어떤 객체 멤버가 반복되거나 키-값 쌍으로 지정 될지 여부가 명확하지 않은 경우 다른 옵션을 사용하면 혼동 될 수 있습니다.
옵션 1a : 클래스를 상속하고 'typing.NamedTuple'(또는 대부분 동등한 'collections.namedtuple') 제공된 _asdict메소드를 사용하십시오 .
from typing import NamedTuple
class Wharrgarbl(NamedTuple):
a: str
b: str
c: str
sum: int = 6
version: str = 'old'
명명 된 튜플을 사용하는 것은 _asdict메서드를 포함 하여 최소한의 노력으로 클래스에 많은 기능을 추가하는 매우 편리한 방법 입니다. 상술 한 바와 같이 다소 한계가 인, 상기 NT는 포함 모든 그것의 부재 _asdict.
사전에 포함하지 않으려는 구성원이있는 경우 _asdict결과 를 수정해야합니다 .
from typing import NamedTuple
class Wharrgarbl(NamedTuple):
a: str
b: str
c: str
sum: int = 6
version: str = 'old'
def _asdict(self):
d = super()._asdict()
del d['sum']
del d['version']
return d
또 다른 제한은 NT가 읽기 전용이라는 것입니다. 이것은 바람직하거나 바람직하지 않을 수 있습니다.
옵션 2 : 구현 __iter__.
예를 들면 다음과 같습니다.
def __iter__(self):
yield 'a', self.a
yield 'b', self.b
yield 'c', self.c
이제 다음을 수행 할 수 있습니다.
dict(my_object)
이는 생성자가 사전을 구성하기 위해 dict()반복 가능한 (key, value)쌍을 허용 하기 때문에 작동합니다 . 이 작업을 수행하기 전에 객체를 일련의 키, 값 쌍으로 반복하는 방식 (만들기에 편리하지만) dict이 실제로 다른 컨텍스트에서 놀라운 동작 일 수 있는지 스스로에게 질문하십시오 . 예를 들어, "의 행동은 무엇이어야 list(my_object)합니까?"라는 질문을 스스로에게 물어보십시오.
또한 항목 가져 오기 obj["a"]구문을 사용하여 값에 직접 액세스하는 것은 작동하지 않으며 키워드 인수 압축 해제도 작동하지 않습니다. 이를 위해서는 매핑 프로토콜을 구현해야합니다.
옵션 3 : 매핑 프로토콜을 구현 합니다 . 이를 통해 키별 액세스 동작을 허용하고 를 사용하지 않고로 캐스팅 할 수 있으며 모든 키가 문자열 ( ) 인 경우 압축 해제 동작 ( ) 및 키워드 압축 해제 동작 도 제공합니다 .dict__iter__{**my_obj}dict(**my_obj)
매핑 프로토콜을 사용하려면 (최소한) 두 가지 방법을 함께 제공해야합니다. keys()및 __getitem__.
class MyKwargUnpackable:
def keys(self):
return list("abc")
def __getitem__(self, key):
return dict(zip("abc", "one two three".split()))[key]
이제 다음과 같은 작업을 수행 할 수 있습니다.
>>> m=MyKwargUnpackable()
>>> m["a"]
'one'
>>> dict(m)
{'a': 'one', 'b': 'two', 'c': 'three'}
>>> dict(**m)
{'a': 'one', 'b': 'two', 'c': 'three'}
위에서 언급했듯이 충분히 새로운 버전의 파이썬을 사용하는 경우 매핑-프로토콜 객체를 다음과 같이 사전 이해로 압축 해제 할 수도 있습니다 (이 경우 키가 문자열 일 필요는 없습니다).
>>> {**m}
{'a': 'one', 'b': 'two', 'c': 'three'}
매핑 프로토콜이 있습니다 보다 우선__iter__ A와 개체를 캐스팅 할 때 방법 dict(즉, kwarg 풀기를 사용하지 않고 직접 dict(m)). 따라서 객체가 반복 가능 (예 :)으로 사용될 list(m)때와 dict( dict(m))로 캐스트 될 때 다른 동작을 갖도록하는 것이 가능하고 때로는 편리합니다 .
강조 : 당신은 매핑 프로토콜을 사용할 수 있습니다해서, 당신은 것을 의미하지 않습니다 안된다 그렇게 . 객체가 키-값 쌍의 집합으로 전달되거나 키워드 인수 및 값으로 전달되는것이 실제로 의미 가 있습니까? 사전처럼 키로 액세스하는 것이 정말 의미가 있습니까?
이러한 질문에 대한 대답이 예 이면 다음 옵션을 고려하는 것이 좋습니다.
옵션 4 : 'collections.abc'모듈 사용을 고려하십시오 .
클래스를 상속 'collections.abc.Mapping하거나 'collections.abc.MutableMapping다른 사용자에게 신호를 보내면 모든 인 텐트와 목적을 위해 클래스 가 매핑 *이며 그런 방식으로 작동 할 것으로 예상 할 수 있습니다.
원하는대로 개체를 캐스트 할 수 dict있지만 그렇게 할 이유가 거의 없을 것입니다. 덕 타이핑 때문에 매핑 객체를로 캐스팅 dict하는 것은 대부분의 경우 불필요한 추가 단계 일뿐입니다.
이 답변 도 도움 이 될 수 있습니다.
아래 주석에서 언급했듯이이 작업을 수행하면 abc 방식으로 기본적으로 객체 클래스가 dict유사 클래스 로 바뀐다는 점을 언급 할 가치가 있습니다 ( MutableMapping읽기 전용 Mapping기본 클래스 가 아니라 사용한다고 가정 ). 으로 할 수있는 모든 dict작업은 자신의 클래스 객체로 할 수 있습니다. 이것은 바람직하거나 바람직하지 않을 수 있습니다.
또한 numbers모듈 의 숫자 abc를 살펴보십시오 .
https://docs.python.org/3/library/numbers.html
또한 객체를으로 캐스팅하므로 캐스팅이 필요하지 않도록 int기본적으로 클래스를 본격적인 클래스로 바꾸는 것이 더 합리적 일 수 있습니다 int.
옵션 5 : 편리한 유틸리티 방법 이 포함 된 dataclasses모듈 (Python 3.7 만 해당) 사용을 살펴 봅니다 asdict().
from dataclasses import dataclass, asdict, field, InitVar
@dataclass
class Wharrgarbl(object):
a: int
b: int
c: int
sum: InitVar[int]
version: InitVar[str] = "old"
def __post_init__(self, sum, version):
self.sum = 6
self.version = str(version)
이제 다음과 같이 할 수 있습니다.
>>> asdict(Wharrgarbl(1,2,3,4,"X"))
{'a': 1, 'b': 2, 'c': 3}
옵션 6 : python 3.8typing.TypedDict 에 추가 된을 사용 합니다.
참고 : 옵션 6은 가능성이 NOT 영업 이익, 또는이 질문의 제목에 따라 다른 독자가 찾고있는 것을. 아래의 추가 설명을 참조하십시오.
class Wharrgarbl(TypedDict):
a: str
b: str
c: str
이 옵션을 사용하면 결과 객체 는입니다dict (강조 : a 가 아님Wharrgarbl ). (복사를하지 않는 한) dict에 "캐스트"할 이유가 전혀 없습니다.
그리고 객체 가dict 이므로 초기화 서명은의 dict그것과 동일하므로 키워드 인수 또는 다른 사전 만 허용합니다.
>>> w = Wharrgarbl(a=1,b=2,b=3)
>>> w
{'a': 1, 'b': 2, 'c': 3}
>>> type(w)
<class 'dict'>
강조 : 위의 "클래스" Wharrgarbl는 실제로 새로운 클래스가 아닙니다. dict유형 검사기에 대해 서로 다른 유형의 필드 를 사용하여 유형이 지정된 객체 를 생성하기위한 단순한 구문 설탕입니다 .
따라서이 옵션은 코드 판독기 (및 mypy와 같은 유형 검사기)에게 이러한 dict객체가 특정 값 유형을 가진 특정 키를 가질 것으로 예상 된다는 신호를 보내는 데 매우 편리 할 수 있습니다 .
그러나 이것은 예를 들어 시도 할 수 있지만 다른 방법을 추가 할 수 없음을 의미합니다.
class MyDict(TypedDict):
def my_fancy_method(self):
return "world changing result"
...하지만 작동하지 않습니다.
>>> MyDict().my_fancy_method()
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
AttributeError: 'dict' object has no attribute 'my_fancy_method'
* "매핑"은 dict오리와 같은 유형 의 표준 "이름"이되었습니다.