programing

사전의 구성원에 액세스하기 위해 점 ". "을(를) 사용하는 방법

sourcejob 2022. 9. 30. 11:05
반응형

사전의 구성원에 액세스하기 위해 점 ". "을(를) 사용하는 방법

Python 사전 구성원에 점 "?"을 통해 접근할 수 있도록 하려면 어떻게 해야 합니다.

를 들어, '는 것이 '는 것이 좋다'라고 씁니다.mydict['val'] 쓰고 mydict.val.

또, 네스트 된 딕트에도 액세스 하고 싶습니다.예를들면

mydict.mydict2.val 

참조할 수 있다

mydict = { 'mydict2': { 'val': ... } }

항상 이걸 util 파일로 보관해뒀어요당신의 수업에서도 믹스로 사용할 수 있습니다.

class dotdict(dict):
    """dot.notation access to dictionary attributes"""
    __getattr__ = dict.get
    __setattr__ = dict.__setitem__
    __delattr__ = dict.__delitem__

mydict = {'val':'it works'}
nested_dict = {'val':'nested works too'}
mydict = dotdict(mydict)
mydict.val
# 'it works'

mydict.nested = dotdict(nested_dict)
mydict.nested.val
# 'nested works too'

내가방 、 업업업업업할 。에서는, 「」를 할 수 .Map다른 사전(json 직렬화 포함)과 같은 객체 또는 점 표기법.도움이 되었으면 합니다.

class Map(dict):
    """
    Example:
    m = Map({'first_name': 'Eduardo'}, last_name='Pool', age=24, sports=['Soccer'])
    """
    def __init__(self, *args, **kwargs):
        super(Map, self).__init__(*args, **kwargs)
        for arg in args:
            if isinstance(arg, dict):
                for k, v in arg.iteritems():
                    self[k] = v

        if kwargs:
            for k, v in kwargs.iteritems():
                self[k] = v

    def __getattr__(self, attr):
        return self.get(attr)

    def __setattr__(self, key, value):
        self.__setitem__(key, value)

    def __setitem__(self, key, value):
        super(Map, self).__setitem__(key, value)
        self.__dict__.update({key: value})

    def __delattr__(self, item):
        self.__delitem__(item)

    def __delitem__(self, key):
        super(Map, self).__delitem__(key)
        del self.__dict__[key]

사용 예:

m = Map({'first_name': 'Eduardo'}, last_name='Pool', age=24, sports=['Soccer'])
# Add new key
m.new_key = 'Hello world!'
# Or
m['new_key'] = 'Hello world!'
print m.new_key
print m['new_key']
# Update values
m.new_key = 'Yay!'
# Or
m['new_key'] = 'Yay!'
# Delete key
del m.new_key
# Or
del m['new_key']

dotmap★★★★★★★★★★★★★★★★★를 통해pip

pip install dotmap

은 당신이 을 하고 분류를 합니다.dict

from dotmap import DotMap

m = DotMap()
m.hello = 'world'
m.hello
m.hello += '!'
# m.hello and m['hello'] now both return 'world!'
m.val = 5
m.val2 = 'Sam'

,, 이, 이, 이, 이, 이, 이, 이, 능, on, on, on, on, on, on, on, on, on, on, on, on로 변환할 수 .dict★★★★★★★★★★★★★★★★★★:

d = m.toDict()
m = DotMap(d) # automatic conversion in constructor

은, 「」에 , 「」라고 하는 입니다.dict 해서 형상으로 수 요.DotMap쉽게 접근할 수 있습니다.

import json
jsonDict = json.loads(text)
data = DotMap(jsonDict)
print data.location.city

됩니다.DotMap을 사용하다

m = DotMap()
m.people.steve.age = 31

번치와의 비교

완전 공개:는 닷맵을 만든 사람입니다.제가 만든 이유는Bunch되어 있었습니다.

  • 순서 항목이 추가되고 해당 순서로 반복된다는 것을 기억하십시오.
  • 아이DotMapcreation을때 더 됩니다.
  • 성 a로 dict를 재귀적으로 합니다.dict인스턴스 에대한에 인스턴스DotMap

이러할 것이라 맹세에서 dict구현에서 파생됩니다 및을 구현합니다.__getattr__그리고 그리고.__setattr__..

아니면 아주 비슷한 번치를 사용하셔도 됩니다.

빌트인 딕트 수업을 멍키패치하는 건 불가능할 것 같아.

사용 사용하다SimpleNamespace::

>>> from types import SimpleNamespace   
>>> d = dict(x=[1, 2], y=['a', 'b'])
>>> ns = SimpleNamespace(**d)
>>> ns.x
[1, 2]
>>> ns
namespace(x=[1, 2], y=['a', 'b'])

패브릭의 실장은 매우 훌륭하고 최소한으로 억제되어 있습니다.네스트된 접근을 허용하도록 확장하면defaultdict하게 되었고, 결과: 이렇게 생겼습니다.결과는 다음과 같습니다.

from collections import defaultdict

class AttributeDict(defaultdict):
    def __init__(self):
        super(AttributeDict, self).__init__(AttributeDict)

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

    def __setattr__(self, key, value):
        self[key] = value

다음과 같이 사용합니다.

keys = AttributeDict()
keys.abc.xyz.x = 123
keys.abc.xyz.a.b.c = 234

이는 쿠겔이 "Derive from dict and explement and"라고 대답한 내용을 조금 더 자세히 설명한 것이다.이제 방법을 알겠군!

이거 해봤어요.

class dotdict(dict):
    def __getattr__(self, name):
        return self[name]

당신해볼 수 만들어 볼 수 있는 있습니다__getattribute__too.너무.

만약 당신이 다층 것이라 맹세에서, 모든 dit를dotdict유형으로 만들면 충분합니다 도굴 init고 싶dotdict의 모든 것이라 맹세 형식, 좋을 것이다.여러레이어 dit에서 초기화하려면 보십시오구현해 이것을.__init__too.너무.

나는 최근에 같은 일을 하는 '박스' 도서관을 우연히 발견했다.

설치 명령:설치 명령:pip install python-box

예제:

from box import Box

mydict = {"key1":{"v1":0.375,
                    "v2":0.625},
          "key2":0.125,
          }
mydict = Box(mydict)

print(mydict.key1.v1)

큰 네스트된 딕트가 있을 때 파이썬 재귀 오류를 발생시키는 닷맵과 같은 기존 라이브러리보다 더 효과적이라는 것을 알게 되었습니다.

라이브러리 및 상세 링크:https://pypi.org/project/python-box/

수정된 사전을 피클하려면 위의 답변에 몇 가지 상태 방법을 추가해야 합니다.

class DotDict(dict):
    """dot.notation access to dictionary attributes"""
    def __getattr__(self, attr):
        return self.get(attr)
    __setattr__= dict.__setitem__
    __delattr__= dict.__delitem__

    def __getstate__(self):
        return self

    def __setstate__(self, state):
        self.update(state)
        self.__dict__ = self

하지 마세요. 속성 액세스와 인덱싱은 Python에서는 별개입니다.이것들이 같은 처리를 하는 것을 원하지 않습니다.클래스를 만듭니다(아마도 에 의해 만들어진 클래스).namedtuple하여 Atribute를 사용해야 []에서 입니다.

이것은 Simple Namespace를 사용하여 실행할 수 있습니다.

from types import SimpleNamespace
# Assign values
args = SimpleNamespace()
args.username = 'admin'

# Retrive values
print(args.username)  # output: admin

쿠겔의 대답을 바탕으로 마이크 그레이엄의 경고문을 참고해서 포장지를 만들면 어떨까?

class DictWrap(object):
  """ Wrap an existing dict, or create a new one, and access with either dot 
    notation or key lookup.

    The attribute _data is reserved and stores the underlying dictionary.
    When using the += operator with create=True, the empty nested dict is 
    replaced with the operand, effectively creating a default dictionary
    of mixed types.

    args:
      d({}): Existing dict to wrap, an empty dict is created by default
      create(True): Create an empty, nested dict instead of raising a KeyError

    example:
      >>>dw = DictWrap({'pp':3})
      >>>dw.a.b += 2
      >>>dw.a.b += 2
      >>>dw.a['c'] += 'Hello'
      >>>dw.a['c'] += ' World'
      >>>dw.a.d
      >>>print dw._data
      {'a': {'c': 'Hello World', 'b': 4, 'd': {}}, 'pp': 3}

  """

  def __init__(self, d=None, create=True):
    if d is None:
      d = {}
    supr = super(DictWrap, self)  
    supr.__setattr__('_data', d)
    supr.__setattr__('__create', create)

  def __getattr__(self, name):
    try:
      value = self._data[name]
    except KeyError:
      if not super(DictWrap, self).__getattribute__('__create'):
        raise
      value = {}
      self._data[name] = value

    if hasattr(value, 'items'):
      create = super(DictWrap, self).__getattribute__('__create')
      return DictWrap(value, create)
    return value

  def __setattr__(self, name, value):
    self._data[name] = value  

  def __getitem__(self, key):
    try:
      value = self._data[key]
    except KeyError:
      if not super(DictWrap, self).__getattribute__('__create'):
        raise
      value = {}
      self._data[key] = value

    if hasattr(value, 'items'):
      create = super(DictWrap, self).__getattribute__('__create')
      return DictWrap(value, create)
    return value

  def __setitem__(self, key, value):
    self._data[key] = value

  def __iadd__(self, other):
    if self._data:
      raise TypeError("A Nested dict will only be replaced if it's empty")
    else:
      return other

epool의 답변을 기반으로 하기 위해 이 버전에서는 닷 연산자를 통해 안에 있는 모든 dict에 액세스할 수 있습니다.

foo = {
    "bar" : {
        "baz" : [ {"boo" : "hoo"} , {"baba" : "loo"} ]
    }
}

를 들면, 「 」입니다.foo.bar.baz[1].baba"loo".

class Map(dict):
    def __init__(self, *args, **kwargs):
        super(Map, self).__init__(*args, **kwargs)
        for arg in args:
            if isinstance(arg, dict):
                for k, v in arg.items():
                    if isinstance(v, dict):
                        v = Map(v)
                    if isinstance(v, list):
                        self.__convert(v)
                    self[k] = v

        if kwargs:
            for k, v in kwargs.items():
                if isinstance(v, dict):
                    v = Map(v)
                elif isinstance(v, list):
                    self.__convert(v)
                self[k] = v

    def __convert(self, v):
        for elem in range(0, len(v)):
            if isinstance(v[elem], dict):
                v[elem] = Map(v[elem])
            elif isinstance(v[elem], list):
                self.__convert(v[elem])

    def __getattr__(self, attr):
        return self.get(attr)

    def __setattr__(self, key, value):
        self.__setitem__(key, value)

    def __setitem__(self, key, value):
        super(Map, self).__setitem__(key, value)
        self.__dict__.update({key: value})

    def __delattr__(self, item):
        self.__delitem__(item)

    def __delitem__(self, key):
        super(Map, self).__delitem__(key)
        del self.__dict__[key]

__getattr__심플한 3..3에서

class myDict(dict):
    def __getattr__(self,val):
        return self[val]


blockBody=myDict()
blockBody['item1']=10000
blockBody['item2']="StackOverflow"
print(blockBody.item1)
print(blockBody.item2)

출력:

10000
StackOverflow

나는 뭉크를 좋아하고 닷 액세스 외에 편리한 옵션도 많이 제공한다.

수입 뭉크

temp_1 = {'person': {fname': 'senthil', 'lname': 'ramalingam'}

dict_munch=munch.munchify(munch_1)

dict_dict.person.fname

언어 자체는 이를 지원하지 않지만, 때때로 이것은 여전히 유용한 요구 사항입니다.Bunch 레시피 외에 점 문자열로 사전에 접속할 수 있는 간단한 메서드도 작성할 수 있습니다.

def get_var(input_dict, accessor_string):
    """Gets data from a dictionary using a dotted accessor-string"""
    current_data = input_dict
    for chunk in accessor_string.split('.'):
        current_data = current_data.get(chunk, {})
    return current_data

다음과 같은 것을 지원할 수 있습니다.

>> test_dict = {'thing': {'spam': 12, 'foo': {'cheeze': 'bar'}}}
>> output = get_var(test_dict, 'thing.spam.foo.cheeze')
>> print output
'bar'
>>

저는 결국 AttrDict와 Bunch 라이브러리 둘 다 시도해 보았고, 그것들이 제 용도에 비해 느리다는 것을 알게 되었습니다.친구와 제가 조사한 결과, 이러한 라이브러리를 쓰는 주요 방법은 라이브러리가 중첩된 오브젝트를 통해 공격적으로 반복되고 사전 오브젝트의 복사본을 만드는 결과를 초래한다는 것을 알게 되었습니다.이를 고려하여 두 가지 중요한 변경을 가했습니다. 1) 속성을 느리게 로드 2) 사전 객체의 복사본을 만드는 대신 경량 프록시 객체의 복사본을 만듭니다.이것이 최종 구현입니다.이 코드를 사용하면 퍼포먼스가 크게 향상됩니다.AttrDict 또는 Bunch를 사용할 때 이 두 라이브러리만 요청 시간의 1/2와 1/3을 소비했습니다(What!?).이 코드에 의해, 그 시간이 거의 제로(0.5ms 의 범위)로 단축되었습니다.이것은 물론 고객의 요구에 따라 다르지만, 코드에서 이 기능을 꽤 많이 사용하고 있는 경우는, 반드시 다음과 같은 심플한 것을 선택해 주세요.

class DictProxy(object):
    def __init__(self, obj):
        self.obj = obj

    def __getitem__(self, key):
        return wrap(self.obj[key])

    def __getattr__(self, key):
        try:
            return wrap(getattr(self.obj, key))
        except AttributeError:
            try:
                return self[key]
            except KeyError:
                raise AttributeError(key)

    # you probably also want to proxy important list properties along like
    # items(), iteritems() and __len__

class ListProxy(object):
    def __init__(self, obj):
        self.obj = obj

    def __getitem__(self, key):
        return wrap(self.obj[key])

    # you probably also want to proxy important list properties along like
    # __iter__ and __len__

def wrap(value):
    if isinstance(value, dict):
        return DictProxy(value)
    if isinstance(value, (tuple, list)):
        return ListProxy(value)
    return value

https://stackoverflow.com/users/704327/michael-merickel실장 원본을 참조해 주세요.

또 하나 주의할 점은 이 구현은 매우 단순하며 필요한 모든 방법을 구현하지는 않는다는 것입니다.필요에 따라 DictProxy 또는 ListProxy 오브젝트에 기입해야 합니다.

def dict_to_object(dick):
    # http://stackoverflow.com/a/1305663/968442

    class Struct:
        def __init__(self, **entries):
            self.__dict__.update(entries)

    return Struct(**dick)

dict이의를 제기할 수 있습니다.액세스하기 직전에 일회용 개체를 만들 수 있습니다.

d = dict_to_object(d)

이 솔루션은 epool에서 제공하는 솔루션을 개량한 것으로, OP가 네스트된 dict에 일관되게 액세스 할 수 있도록 합니다.epool별 솔루션에서는 중첩된 딕트에 액세스할 수 없습니다.

class YAMLobj(dict):
    def __init__(self, args):
        super(YAMLobj, self).__init__(args)
        if isinstance(args, dict):
            for k, v in args.iteritems():
                if not isinstance(v, dict):
                    self[k] = v
                else:
                    self.__setattr__(k, YAMLobj(v))


    def __getattr__(self, attr):
        return self.get(attr)

    def __setattr__(self, key, value):
        self.__setitem__(key, value)

    def __setitem__(self, key, value):
        super(YAMLobj, self).__setitem__(key, value)
        self.__dict__.update({key: value})

    def __delattr__(self, item):
        self.__delitem__(item)

    def __delitem__(self, key):
        super(YAMLobj, self).__delitem__(key)
        del self.__dict__[key]

할 수 A.B.C.D

dict, 목록, dict 목록 및 dict 목록의 무한 중첩 수준.

피클링도 지원

이것은 이 답변의 연장선입니다.

class DotDict(dict):
    # https://stackoverflow.com/a/70665030/913098
    """
    Example:
    m = Map({'first_name': 'Eduardo'}, last_name='Pool', age=24, sports=['Soccer'])

    Iterable are assumed to have a constructor taking list as input.
    """

    def __init__(self, *args, **kwargs):
        super(DotDict, self).__init__(*args, **kwargs)

        args_with_kwargs = []
        for arg in args:
            args_with_kwargs.append(arg)
        args_with_kwargs.append(kwargs)
        args = args_with_kwargs

        for arg in args:
            if isinstance(arg, dict):
                for k, v in arg.items():
                    self[k] = v
                    if isinstance(v, dict):
                        self[k] = DotDict(v)
                    elif isinstance(v, str) or isinstance(v, bytes):
                        self[k] = v
                    elif isinstance(v, Iterable):
                        klass = type(v)
                        map_value: List[Any] = []
                        for e in v:
                            map_e = DotDict(e) if isinstance(e, dict) else e
                            map_value.append(map_e)
                        self[k] = klass(map_value)



    def __getattr__(self, attr):
        return self.get(attr)

    def __setattr__(self, key, value):
        self.__setitem__(key, value)

    def __setitem__(self, key, value):
        super(DotDict, self).__setitem__(key, value)
        self.__dict__.update({key: value})

    def __delattr__(self, item):
        self.__delitem__(item)

    def __delitem__(self, key):
        super(DotDict, self).__delitem__(key)
        del self.__dict__[key]

    def __getstate__(self):
        return self.__dict__

    def __setstate__(self, d):
        self.__dict__.update(d)


if __name__ == "__main__":
    import pickle
    def test_map():
        d = {
            "a": 1,
            "b": {
                "c": "d",
                "e": 2,
                "f": None
            },
            "g": [],
            "h": [1, "i"],
            "j": [1, "k", {}],
            "l":
                [
                    1,
                    "m",
                    {
                        "n": [3],
                        "o": "p",
                        "q": {
                            "r": "s",
                            "t": ["u", 5, {"v": "w"}, ],
                            "x": ("z", 1)
                        }
                    }
                ],
        }
        map_d = DotDict(d)
        w = map_d.l[2].q.t[2].v
        assert w == "w"

        pickled = pickle.dumps(map_d)
        unpickled = pickle.loads(pickled)
        assert unpickled == map_d

        kwargs_check = DotDict(a=1, b=[dict(c=2, d="3"), 5])
        assert kwargs_check.b[0].d == "3"

        kwargs_and_args_check = DotDict(d, a=1, b=[dict(c=2, d="3"), 5])
        assert kwargs_and_args_check.l[2].q.t[2].v == "w"
        assert kwargs_and_args_check.b[0].d == "3"



    test_map()

이 방법은 중첩된 딕트에서도 작동하며 나중에 추가된 딕트도 동일하게 동작합니다.

class DotDict(dict):

    def __init__(self, *args, **kwargs):
        super().__init__(*args, **kwargs)
        # Recursively turn nested dicts into DotDicts
        for key, value in self.items():
            if type(value) is dict:
                self[key] = DotDict(value)

    def __setitem__(self, key, item):
        if type(item) is dict:
            item = DotDict(item)
        super().__setitem__(key, item)

    __setattr__ = __setitem__
    __getattr__ = dict.__getitem__

「」를 사용합니다.namedtuple도트 액세스를 허용합니다.

그것은 태플의 성질을 가지고 있는 가벼운 물건과 같다.

도트 연산자를 사용하여 속성을 정의하고 액세스할 수 있습니다.

from collections import namedtuple
Data = namedtuple('Data', ['key1', 'key2'])

dataObj = Data(val1, key2=val2) # can instantiate using keyword arguments and positional arguments

도트 연산자를 사용하여 액세스

dataObj.key1 # Gives val1
datObj.key2 # Gives val2

태플 인덱스를 사용한 액세스

dataObj[0] # Gives val1
dataObj[1] # Gives val2

하지만 이것은 명령어가 아니라 태플이라는 것을 기억해라.그래서 아래 코드는 오류를 줄 것이다.

dataObj['key1'] # Gives TypeError: tuple indices must be integers or slices, not str

참조: named tuple

오래된 질문이지만 최근에 알게 된 것은sklearn에는, 「」이 .dict로 할 수 즉 「」, 「」Bunch https://scikit-learn.org/stable/modules/generated/sklearn.utils.Bunch.html#sklearn.utils.Bunchhttps.org/stable/modules/generated/sklearn.utils.Bunch.html#sklearn.utils.Bunch

가장 심플한 솔루션

pass 문만 포함하는 클래스를 정의합니다.이 클래스에 대한 개체를 만들고 점 표기법을 사용합니다.

class my_dict:
    pass

person = my_dict()
person.id = 1 # create using dot notation
person.phone = 9999
del person.phone # Remove a property using dot notation

name_data = my_dict()
name_data.first_name = 'Arnold'
name_data.last_name = 'Schwarzenegger'

person.name = name_data
person.name.first_name # dot notation access for nested properties - gives Arnold

도트 액세스(어레이 액세스가 아님)를 얻는 간단한 방법 중 하나는 Python에서 플레인 오브젝트를 사용하는 것입니다.다음과 같이 합니다.

class YourObject:
    def __init__(self, *args, **kwargs):
        for k, v in kwargs.items():
            setattr(self, k, v)

...그리고 다음과 같이 사용합니다.

>>> obj = YourObject(key="value")
>>> print(obj.key)
"value"

...dict로 변환하려면:

>>> print(obj.__dict__)
{"key": "value"}

@derek73의 답변은 매우 깔끔하지만 절이거나 복사할 수 없으며, 다시 돌아온다.None을 사용하다이 문제는 다음 코드로 해결됩니다.

편집: 위의 답변에서 동일한 포인트(업보드)를 다루는 답변을 찾을 수 없습니다.참고로 여기에 답을 남깁니다.

class dotdict(dict):
    __setattr__ = dict.__setitem__
    __delattr__ = dict.__delitem__

    def __getattr__(self, name):
        try:
            return self[name]
        except KeyError:
            raise AttributeError(name)

점선 경로 문자열을 사용하여 사전에 액세스해야 했기 때문에 다음과 같은 방법을 생각해 냈습니다.

def get_value_from_path(dictionary, parts):
    """ extracts a value from a dictionary using a dotted path string """

    if type(parts) is str:
        parts = parts.split('.')

    if len(parts) > 1:
        return get_value_from_path(dictionary[parts[0]], parts[1:])

    return dictionary[parts[0]]

a = {'a':{'b':'c'}}
print(get_value_from_path(a, 'a.b')) # c

저는 10년 이상 된 화재에 또 다른 통나무를 추가하는 것은 싫지만, 제가 최근에 내놓은 도서관도 살펴보고 싶습니다. 사실 올해에요.

비교적 작은 라이브러리이기 때문에 벤치마크의 취득(액세스) 및 설정(작성) 시간적어도 다른 대체 라이브러리보다 매우 우수합니다.

dotwiz★★★★★★★★★★★★★★★★★를 통해pip

pip install dotwiz

은 당신이 을 하고 분류를 합니다.dict

from dotwiz import DotWiz

dw = DotWiz()
dw.hello = 'world'
dw.hello
dw.hello += '!'
# dw.hello and dw['hello'] now both return 'world!'
dw.val = 5
dw.val2 = 'Sam'

,, 이, 이, 이, 이, 이, 이, 이, 능, on, on, on, on, on, on, on, on, on, on, on, on로 변환할 수 .dict★★★★★★★★★★★★★★★★★★:

d = dw.to_dict()
dw = DotWiz(d) # automatic conversion in constructor

은, 「」에 , 「」라고 하는 입니다.dict 해서 형상으로 수 요.DotWiz쉽게 접근할 수 있습니다.

import json
json_dict = json.loads(text)
data = DotWiz(json_dict)
print data.location.city

마지막으로, 현재 작업 중인 흥미로운 것은 기존 기능 요청으로, 새로운 자식이 자동으로 생성됩니다.DotWiz인스턴스는 네가:이런 짓을 할 수 있다.다음과 같은 작업을 수행할 수 있습니다.

dw = DotWiz()
dw['people.steve.age'] = 31

dw
# ✫(people=✫(steve=✫(age=31)))

비교 비교와dotmap

아래와 같은 빠른 성능 비교를 추가했습니다.

첫째,먼저 두 라이브러리를모두 설치합니다와 도서관을 설치한다.pip::

pip install dotwiz dotmap

벤치마크를 위해 다음 코드를 생각해 냈습니다.

from timeit import timeit

from dotwiz import DotWiz
from dotmap import DotMap


d = {'hey': {'so': [{'this': {'is': {'pretty': {'cool': True}}}}]}}

dw = DotWiz(d)
# ✫(hey=✫(so=[✫(this=✫(is=✫(pretty={'cool'})))]))

dm = DotMap(d)
# DotMap(hey=DotMap(so=[DotMap(this=DotMap(is=DotMap(pretty={'cool'})))]))

assert dw.hey.so[0].this['is'].pretty.cool == dm.hey.so[0].this['is'].pretty.cool

n = 100_000

print('dotwiz (create):  ', round(timeit('DotWiz(d)', number=n, globals=globals()), 3))
print('dotmap (create):  ', round(timeit('DotMap(d)', number=n, globals=globals()), 3))
print('dotwiz (get):  ', round(timeit("dw.hey.so[0].this['is'].pretty.cool", number=n, globals=globals()), 3))
print('dotmap (get):  ', round(timeit("dm.hey.so[0].this['is'].pretty.cool", number=n, globals=globals()), 3))

M1 Mac에서 Python 3.10을 실행한 결과:

dotwiz (create):   0.189
dotmap (create):   1.085
dotwiz (get):   0.014
dotmap (get):   0.335

아니라 관측소의 질문에 직접적으로 대답이 아니라 물 속에 그리고 아마도 some.에게 유용한 것입니다.OP의 질문에 대한 직접적인 답변은 아니지만,일부에서 영감을 얻었으며,아마도유용한 질문일 것입니다.나는 객체 기반 해결책솔루션을 만들었습니다 기반 객체 내부 내부시스템을 사용하여를 사용하여 만들었습니다.__dict__(방법이 없어 최적화된 코드에서는)(최적화된 코드는 아닙니다).

payload = {
    "name": "John",
    "location": {
        "lat": 53.12312312,
        "long": 43.21345112
    },
    "numbers": [
        {
            "role": "home",
            "number": "070-12345678"
        },
        {
            "role": "office",
            "number": "070-12345679"
        }
    ]
}


class Map(object):
    """
    Dot style access to object members, access raw values
    with an underscore e.g.

    class Foo(Map):
        def foo(self):
            return self.get('foo') + 'bar'

    obj = Foo(**{'foo': 'foo'})

    obj.foo => 'foobar'
    obj._foo => 'foo'

    """

    def __init__(self, *args, **kwargs):
        for arg in args:
            if isinstance(arg, dict):
                for k, v in arg.iteritems():
                    self.__dict__[k] = v
                    self.__dict__['_' + k] = v

        if kwargs:
            for k, v in kwargs.iteritems():
                self.__dict__[k] = v
                self.__dict__['_' + k] = v

    def __getattribute__(self, attr):
        if hasattr(self, 'get_' + attr):
            return object.__getattribute__(self, 'get_' + attr)()
        else:
            return object.__getattribute__(self, attr)

    def get(self, key):
        try:
            return self.__dict__.get('get_' + key)()
        except (AttributeError, TypeError):
            return self.__dict__.get(key)

    def __repr__(self):
        return u"<{name} object>".format(
            name=self.__class__.__name__
        )


class Number(Map):
    def get_role(self):
        return self.get('role')

    def get_number(self):
        return self.get('number')


class Location(Map):
    def get_latitude(self):
        return self.get('lat') + 1

    def get_longitude(self):
        return self.get('long') + 1


class Item(Map):
    def get_name(self):
        return self.get('name') + " Doe"

    def get_location(self):
        return Location(**self.get('location'))

    def get_numbers(self):
        return [Number(**n) for n in self.get('numbers')]


# Tests

obj = Item({'foo': 'bar'}, **payload)

assert type(obj) == Item
assert obj._name == "John"
assert obj.name == "John Doe"
assert type(obj.location) == Location
assert obj.location._lat == 53.12312312
assert obj.location._long == 43.21345112
assert obj.location.latitude == 54.12312312
assert obj.location.longitude == 44.21345112

for n in obj.numbers:
    assert type(n) == Number
    if n.role == 'home':
        assert n.number == "070-12345678"
    if n.role == 'office':
        assert n.number == "070-12345679"

@derek73의 답변은 다음과 같습니다.사용하고 있다dict.__getitem__~하듯이로__getattr__그래서 그것은 여전히그래서 그것은 여전히 던진다를 throw 합니다.KeyErrordict public 메서드의 이름을 " 접두사"로 변경합니다("를 붙이면 다음과 같은 특수한 메서드의 이름 경합이 발생합니다).__get__어떤 것이 설명자 메서드로 계산 처리될 것이다.기술자방법으로 취급됩니다 cm이다. 중요한 할 수 입니다.dict 기본방법이, 수 있습니다. 즉, 키, 즉 , 예를 들면 키, 즉 키, 키, 키, 키, 키, 키, 키, 키, 키, 키, 키, 키, 키, 키, 키, 키, 키, 키, 키, 키, 키, 키, 키, 키, 키, 키, 키, 키, 키, 키, 키, 키, 키, 키, 키, 키, 키, 이런 것들이 있습니다.get,pop,itemssyslog.

class DotDictMeta(type):                                                          
    def __new__(                                                                  
        cls,                                                                      
        name,                                                                     
        bases,                                                                    
        attrs,                                         
        rename_method=lambda n: f'__{n}__',                            
        **custom_methods,                                                         
    ):                                                                            
        d = dict                                                                  
        attrs.update(                                                             
            cls.get_hidden_or_renamed_methods(rename_method),           
            __getattr__=d.__getitem__,                                            
            __setattr__=d.__setitem__,                                            
            __delattr__=d.__delitem__,                                            
            **custom_methods,                                                     
        )                                                                         
        return super().__new__(cls, name, bases, attrs)                           
                                                                                  
    def __init__(self, name, bases, attrs, **_):                                  
        super().__init__(name, bases, attrs)                                      
                                                                                  
    @property                                                                     
    def attribute_error(self):                                                    
        raise AttributeError                                                      
                                                                                  
    @classmethod                                                                  
    def get_hidden_or_renamed_methods(cls, rename_method=None):                  
        public_methods = tuple(                                                   
            i for i in dict.__dict__.items() if not i[0].startswith('__')         
        )                                                                         
        error = cls.attribute_error                                               
        hidden_methods = ((k, error) for k, v in public_methods)                  
        yield from hidden_methods                                                 
        if rename_method:                                                       
            renamed_methods = ((rename_method(k), v) for k, v in public_methods) 
            yield from renamed_methods                                             
                                                                                  
                                                                                  
class DotDict(dict, metaclass=DotDictMeta):                                       
    pass  

                                                                    
                                                                              

DotDict 네임스페이스에서 dict 메서드를 삭제하고 dict 클래스 메서드를 계속 사용할 수 있습니다.다른 dict 인스턴스에서 동작하고 DotDict 여부를 추가로 확인하지 않고 동일한 메서드를 사용하는 경우에도 유용합니다.

dct = dict(a=1)
dot_dct = DotDict(b=2)
foo = {c: i for i, c in enumerate('xyz')}
for d in (dct, dot_dct):
    # you would have to use dct.update and dot_dct.__update methods
    dict.update(d, foo)
    
assert dict.get(dot, 'foo', 0) is 0

언급URL : https://stackoverflow.com/questions/2352181/how-to-use-a-dot-to-access-members-of-dictionary

반응형