sourcecode

파이썬에서 딕트에 도트 표기법을 사용하는 방법은 무엇입니까?

codebag 2023. 7. 17. 20:57
반응형

파이썬에서 딕트에 도트 표기법을 사용하는 방법은 무엇입니까?

인데 . 의 값 접 근 표기법의 하는 표기법dict.

내가 가지고 있다고 치자.test다음과 같이:

>>> test = dict()
>>> test['name'] = 'value'
>>> print(test['name'])
value

하지만 나는 할 수 있기를 바랍니다.test.name갖기 위해value사실 나는 그것을 무시함으로써 그것을 했습니다.__getattr__우리 반의 방법은 다음과 같습니다.

class JuspayObject:

    def __init__(self,response):
        self.__dict__['_response'] = response

    def __getattr__(self,key): 
        try:
            return self._response[key]
        except KeyError,err:
            sys.stderr.write('Sorry no key matches')

그리고 이것은 효과가 있어요!

test.name // I get value.

하지만 문제는 제가 그냥 인쇄할 때입니다.test단독으로 다음과 같은 오류가 발생합니다.

'Sorry no key matches'

왜 이런 일이 생기는 건가요?

이 기능은 이미 표준 라이브러리에 있으므로 해당 클래스를 사용하는 것이 좋습니다.

>>> from types import SimpleNamespace
>>> d = {'key1': 'value1', 'key2': 'value2'}
>>> n = SimpleNamespace(**d)
>>> print(n)
namespace(key1='value1', key2='value2')
>>> n.key2
'value2'

액세스를 및 할 수 " 적인속액통추값가을", " 및제수있다니습다있즉수니습사할문.", " 과같은용을다음정할기거성수정를세스해다있ments▁like"와 같은 문장을 할 수 .n.key = val그리고.del n.key.

딕트로 다시 돌아가려면:

>>> vars(n)
{'key1': 'value1', 'key2': 'value2'}

속성 액세스가 제대로 작동하려면 딕트의 키가 문자열 식별자여야 합니다.

단순 네임스페이스는 Python 3.3에 추가되었습니다.이전 버전의 언어의 경우 동작이 유사합니다.

당신은 자바스크립트에 익숙하고 그런 구문을 빌리고 싶을 것입니다.저는 개인적인 경험으로 이것이 좋은 생각이 아니라고 말할 수 있습니다.

그것은 확실히 덜 장황하고 깔끔해 보이지만, 장기적으로는 그저 모호할 뿐입니다.딕트는 딕트이며, 속성을 가진 객체처럼 행동하려고 하면 아마 (나쁜) 놀라움을 초래할 것입니다.

, 할 수 있습니다.__dict__필요할 때 속성을 지정합니다. 그러면 사용자가 무엇을 하고 있는지 명확하게 알 수 있습니다.또는 사용getattr(obj, 'key')상속 구조 및 클래스 속성도 고려해야 합니다.

하지만 당신의 예를 읽어보면 뭔가 다른 것을 시도하고 있는 것처럼 보입니다.▁the를 찾을 것이기 입니다.__dict__추가 코드가 없는 속성입니다.

답변 외에도 중첩된 딕트에 대한 지원을 추가할 수 있습니다.

from types import SimpleNamespace

class NestedNamespace(SimpleNamespace):
    def __init__(self, dictionary, **kwargs):
        super().__init__(**kwargs)
        for key, value in dictionary.items():
            if isinstance(value, dict):
                self.__setattr__(key, NestedNamespace(value))
            else:
                self.__setattr__(key, value)

nested_namespace = NestedNamespace({
    'parent': {
        'child': {
            'grandchild': 'value'
        }
    },
    'normal_key': 'normal value',
})


print(nested_namespace.parent.child.grandchild)  # value
print(nested_namespace.normal_key)  # normal value

이것은 목록 내부에 있는 딕트에 대한 도트 표기법을 지원하지 않습니다.

이름이 붙은 튜플을 사용할 수 있습니까?

from collections import namedtuple
Test = namedtuple('Test', 'name foo bar')
my_test = Test('value', 'foo_val', 'bar_val')
print(my_test)
print(my_test.name)

__getattr__다른 모든 특성 조회 규칙이 실패한 경우 이를 예비로 사용합니다.당신이 당신의 객체를 "인쇄"하려고 할 때, Python은 다음을 찾습니다.__repr__방법, 그리고 당신이 수업에서 그것을 실행하지 않기 때문에 그것은 결국 전화를 걸게 됩니다.__getattr__(예, Python에서는 메소드도 속성입니다.)어떤 키로 getattr을 호출할지 추측해서는 안 됩니다. 그리고, 가장 중요한 것은,__getattr__해결할 수 없는 경우 AttributeError를 발생시켜야 합니다.key.

참고로: 사용 안 함self.__dict__일반 속성 액세스의 경우 일반 속성 표기법을 사용합니다.

class JuspayObject:

    def __init__(self,response):
        # don't use self.__dict__ here
        self._response = response

    def __getattr__(self,key):
        try:
            return self._response[key]
        except KeyError,err:
            raise AttributeError(key)

이제 클래스에 다른 책임이 없다면(그리고 파이썬 버전이 >= 2.6이고 이전 버전을 지원할 필요가 없다면) 이름이 붙은 튜플을 사용해도 됩니다. http://docs.python.org/2/library/collections.html#collections.namedtuple

class convert_to_dot_notation(dict):
    """
    Access dictionary attributes via dot notation
    """

    __getattr__ = dict.get
    __setattr__ = dict.__setitem__
    __delattr__ = dict.__delitem__


test = {"name": "value"}
data = convert_to_dot_notation(test)
print(data.name)

기본 제공 방법을 사용할 수 있습니다.

import argparse

args = argparse.Namespace()
args.name = 'value'

print(args.name)
# 'value'

또한 원본 딕트는 다음을 통해 얻을 수 있습니다.vars(args).

사용 시 주의해야 합니다.__getattr__많은 내장 파이썬 기능에 사용되기 때문입니다.

이런 걸 시도해 보세요...

class JuspayObject:

    def __init__(self,response):
        self.__dict__['_response'] = response

    def __getattr__(self, key):
        # First, try to return from _response
        try:
            return self.__dict__['_response'][key]
        except KeyError:
            pass
        # If that fails, return default behavior so we don't break Python
        try:
            return self.__dict__[key]
        except KeyError:
            raise AttributeError, key

>>> j = JuspayObject({'foo': 'bar'})
>>> j.foo
'bar'
>>> j
<__main__.JuspayObject instance at 0x7fbdd55965f0>

다음은 중첩된 항목으로 작업하는 간단하고 편리한 점 표기 도우미 예제입니다.

def dict_get(data:dict, path:str, default = None):
    pathList = re.split(r'\.', path, flags=re.IGNORECASE)
    result = data
    for key in pathList:
        try:
            key = int(key) if key.isnumeric() else key 
            result = result[key]
        except:
            result = default
            break
    
    return result

사용 예:

my_dict = {"test1": "str1", "nested_dict": {"test2": "str2"}, "nested_list": ["str3", {"test4": "str4"}]}
print(dict_get(my_dict, "test1"))
# str1
print(dict_get(my_dict, "nested_dict.test2"))
# str2
print(dict_get(my_dict, "nested_list.1.test4"))
# str4

답변에 약간만 추가하면 다음 목록도 지원할 수 있습니다.

class NestedNamespace(SimpleNamespace):
def __init__(self, dictionary, **kwargs):
    super().__init__(**kwargs)
    for key, value in dictionary.items():
        if isinstance(value, dict):
            self.__setattr__(key, NestedNamespace(value))
        elif isinstance(value, list):
            self.__setattr__(key, map(NestedNamespace, value))
        else:
            self.__setattr__(key, value)

2022년 답변:저는 패키지를 만들었습니다. 이것은 빠르고 작은 도서관입니다. 대부분의 경우에 아주 잘 작동하는 것처럼 보입니다.

>>> from dotwiz import DotWiz
>>> test = DotWiz(hello='world')
>>> test.works = True
>>> test
✫(hello='world', works=True)
>>> test.hello
'world'
>>> assert test.works

이 기능은 OmegaConf에 구워집니다.

from omegaconf import OmegaConf

your_dict = {"k" : "v", "list" : [1, {"a": "1", "b": "2", 3: "c"}]}
adot_dict = OmegaConf.create(your_dict)

print(adot_dict.k)
print(adot_dict.list)

설치:

pip install omegaconf

이 lib는 실제로 다음을 위해 만들어진 구성에 유용합니다.

from omegaconf import OmegaConf
cfg = OmegaConf.load('config.yml')
print(cfg.data_path)

나는 사용합니다.dotted_dict패키지:

    >>> from dotted_dict import DottedDict
    >>> test = DottedDict()
    >>> test.name = 'value'
    >>> print(test.name)
    value

에 대한 장점SimpleNamespace

(@win의 답변을 참조하십시오. DottedDict실제dict:

>>> isinstance(test, dict)
True

예를 들어 구성원 자격을 확인할 수 있습니다.

>>> 'name' in test
True

반면에SimpleNamespace당신은 훨씬 덜 읽을 수 있는 것이 필요합니다.hasattr(test, 'name').

사용 안 함DotMap

저는 이것을 어려운 방법으로 발견했습니다.비회원을 참조하는 경우 오류를 발생시키는 대신 추가합니다.이로 인해 코드에서 버그를 찾기 어려울 수 있습니다.

>>> from dotmap import DotMap
>>> dm = DotMap()
>>> 'a' in dm
False
>>> x = dm.a
>>> 'a' in dm
True
#!/usr/bin/env python3


import json
from sklearn.utils import Bunch
from collections.abc import MutableMapping


def dotted(inpt: MutableMapping,
           *args,
           **kwargs
           ) -> Bunch:
    """
    Enables recursive dot notation for ``dict``.
    """

    return json.loads(json.dumps(inpt),
                      object_hook=lambda x:
                      Bunch(**{**Bunch(), **x}))

딕트에 도트 표기법을 추가하는 해킹을 대부분 작동시킬 수 있지만 네임스페이스 문제가 항상 발생합니다.여기서, 이것은 무엇을 합니까?

x = DotDict()
x["values"] = 1989
print(x. values)

저는 JS의 lodash의 Python 포트인 pydash를 사용하여 둥지가 너무 못생겼을 때 다른 방식으로 이러한 작업을 수행합니다.

추가 a__repr__()표시할 텍스트를 사용자 정의할 수 있도록 클래스에 대한 메소드

print text

여기서 자세히 알아보기: https://web.archive.org/web/20121022015531/http ://diveintopython.net/object_oriented_framework/special_class_methods2.html

언급URL : https://stackoverflow.com/questions/16279212/how-to-use-dot-notation-for-dict-in-python

반응형