내가 묻는 질문에 대답
파이썬은 왜 그것을 즉시 제공하지 않습니까?
파이썬 의 선과 관련 이 있다고 생각합니다 . "한 가지 확실한 방법이 있어야합니다." 이 사전에서 액세스 값이 분명한 방법을 만들 것입니다 : obj['key']
및obj.key
.
경고와 함정
여기에는 코드의 명확성 및 혼란 부족이 포함됩니다. 즉, 다음 에 나중에 코드를 유지 관리 하려는 다른 사람이나 잠시 동안 코드를 다시 사용하지 않으면 다른 사람 에게 혼란을 줄 수 있습니다 . 다시 Zen에서 : "가독성이 중요합니다!"
>>> KEY = 'spam'
>>> d[KEY] = 1
>>> # Several lines of miscellaneous code here...
... assert d.spam == 1
경우 d
인스턴스화 또는 KEY
정의 또는 d[KEY]
멀리 떨어진 곳에서 할당d.spam
사용되는이 일반적으로 사용되는 관용구하지 않기 때문에, 그것은 쉽게 이루어지고 있는지에 대한 혼란으로 이어질 수 있습니다. 나는 그것이 나를 혼란스럽게 할 가능성이 있다는 것을 안다.
KEY
또한 다음과 같이 값을 변경하면 변경 사항이 누락됩니다 d.spam
.
>>> KEY = 'foo'
>>> d[KEY] = 1
>>> # Several lines of miscellaneous code here...
... assert d.spam == 1
Traceback (most recent call last):
File "<stdin>", line 2, in <module>
AttributeError: 'C' object has no attribute 'spam'
노력할 가치가없는 IMO.
다른 물건들
다른 사람들이 지적했듯이 문자열만이 아닌 해시 가능 객체를 dict 키로 사용할 수 있습니다. 예를 들어
>>> d = {(2, 3): True,}
>>> assert d[(2, 3)] is True
>>>
합법적이지만
>>> C = type('C', (object,), {(2, 3): True})
>>> d = C()
>>> assert d.(2, 3) is True
File "<stdin>", line 1
d.(2, 3)
^
SyntaxError: invalid syntax
>>> getattr(d, (2, 3))
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
TypeError: getattr(): attribute name must be string
>>>
아니다. 이를 통해 객체 속성에 액세스 할 때 보유 할 수없는 사전 키에 대해 인쇄 가능한 모든 문자 또는 기타 해시 가능 객체에 액세스 할 수 있습니다. 이를 통해 Python Cookbook (Ch. 9) 의 레시피와 같은 캐시 된 객체 메타 클래스와 같은 마술이 가능해 집니다.
내가 편집하는 곳
나는 spam.eggs
이상의 미학을 선호하고 spam['eggs']
(더 깨끗해 보인다고 생각합니다 namedtuple
.)를 만났을 때이 기능을 갈망하기 시작했습니다 . 그러나 다음을 수행 할 수 있다는 편의성이 우선합니다.
>>> KEYS = 'spam eggs ham'
>>> VALS = [1, 2, 3]
>>> d = {k: v for k, v in zip(KEYS.split(' '), VALS)}
>>> assert d == {'spam': 1, 'eggs': 2, 'ham': 3}
>>>
이것은 간단한 예이지만, obj.key
표기법을 사용하는 것과 다른 상황에서 (예 : XML 파일에서 사전 설정을 읽어야 할 때) dicts를 자주 사용 합니다. 다른 경우에는 미학적 이유로 동적 클래스를 인스턴스화하고 그에 대한 일부 특성을 포기하려는 유혹을받는 경우 가독성을 높이기 위해 일관성에 대한 dict을 계속 사용합니다.
OP가 오랫동안 만족스럽게 해결 한 것으로 확신하지만 여전히이 기능을 원한다면 pypi에서 패키지 중 하나를 다운로드하여 제안합니다.
무리 는 내가 더 친숙한 것입니다. 의 하위 클래스dict
이므로 모든 기능이 있습니다.
AttrDict 도 꽤 좋은 것처럼 보이지만 나는 그것에 익숙하지 않고 Bunch 만큼 많은 소스를 보지 못했습니다.
- Addict 적극적으로 유지 관리되며 attr와 같은 액세스 등을 제공합니다.
- Rotareti의 의견에서 언급했듯이 Bunch는 더 이상 사용되지 않지만 Munch 라는 활성 포크가 있습니다.
그러나 코드의 가독성을 향상시키기 위해 그의 표기 스타일을 혼합 하지 않는 것이 좋습니다 . 이 표기법을 선호하는 경우에는 동적 객체를 인스턴스화하고 원하는 속성을 추가 한 다음 하루에 호출해야합니다.
>>> C = type('C', (object,), {})
>>> d = C()
>>> d.spam = 1
>>> d.eggs = 2
>>> d.ham = 3
>>> assert d.__dict__ == {'spam': 1, 'eggs': 2, 'ham': 3}
주석에서 후속 질문에 대답하기 위해 업데이트
엘모 는 다음 과 같은 의견에서 다음과 같이 묻습니다.
더 깊이 가고 싶다면 어떻게해야합니까? (type (...) 참조)
이 유스 케이스를 사용한 적이 없지만 ( dict
일관 적으로 nested를 사용하는 경향이 있지만 ) 다음 코드가 작동합니다.
>>> C = type('C', (object,), {})
>>> d = C()
>>> for x in 'spam eggs ham'.split():
... setattr(d, x, C())
... i = 1
... for y in 'one two three'.split():
... setattr(getattr(d, x), y, i)
... i += 1
...
>>> assert d.spam.__dict__ == {'one': 1, 'two': 2, 'three': 3}
collections.namedtuple
이것에 매우 유용합니다.