다양한 깊이의 중첩 된 사전 값 업데이트


162

덮어 쓰기 레벨 A를 사용하여 dict update1의 내용으로 dict dictionary1을 업데이트하는 방법을 찾고 있습니다.

dictionary1={'level1':{'level2':{'levelA':0,'levelB':1}}}
update={'level1':{'level2':{'levelB':10}}}
dictionary1.update(update)
print dictionary1
{'level1': {'level2': {'levelB': 10}}}

업데이트는 가장 낮은 키 level1을 업데이트하기 때문에 level2의 값을 삭제한다는 것을 알고 있습니다.

dictionary1과 update가 길이를 가질 수 있다면 어떻게 해결할 수 있습니까?


중첩은 항상 3 단계 깊이입니까, 아니면 임의의 깊이 중첩이 가능합니까?
ChristopheD

깊이 / 길이를 가질 수 있습니다.
jay_t

내가 틀렸다면 정정하십시오. 그러나 이상적인 솔루션처럼 보이는 것은 복합 디자인 패턴의 구현입니다.
Alexander McNulty

답변:


263

@FM의 대답은 올바른 일반적인 아이디어, 즉 재귀 솔루션이지만 다소 독특한 코딩과 적어도 하나의 버그를 가지고 있습니다. 대신 권장합니다.

파이썬 2 :

import collections

def update(d, u):
    for k, v in u.iteritems():
        if isinstance(v, collections.Mapping):
            d[k] = update(d.get(k, {}), v)
        else:
            d[k] = v
    return d

파이썬 3 :

import collections.abc

def update(d, u):
    for k, v in u.items():
        if isinstance(v, collections.abc.Mapping):
            d[k] = update(d.get(k, {}), v)
        else:
            d[k] = v
    return d

"업데이트"가있을 때까지 버그 쇼 k, v항목 vA는 dict하고 k원래 업데이트되는 사전에서 키가 아닌 - 그것은 비어있는 새에 그것을 수행하기 때문에 (FM의 코드 "건너 뜀"@ 업데이트의이 부분을 dict어떤 재귀 호출이 반환되면 손실되거나 저장되지 않습니다).

내 다른 변경 사항은 사소합니다. 동일한 작업을 더 빠르고 깔끔하게 수행 할 때 if/ else구문에 대한 이유가 없으며 일반성을 위해 추상 기본 클래스 (구체 클래스가 아닌)에 가장 적합합니다..getisinstance


7
버그에 +1 잘 잡기-doh! 나는 누군가가 isinstance테스트 를 처리하는 더 좋은 방법을 가질 것이라고 생각했지만, 나는 그것을 찌르겠다고 생각했다.
FMc

6
또 다른 작은 "기능"은 TypeError: 'int' object does not support item assignment.예를 들어 update({'k1': 1}, {'k1': {'k2': 2}}). 이 동작을 변경하고 대신 사전 깊이를 확장하여 더 깊은 사전을위한 공간을 확보 하려면 조건 elif isinstance(d, Mapping):주변 d[k] = u[k]과 주변에 추가 할 수 있습니다 isinstance. 또한 else: d = {k: u[k]}업데이트 dict이 원래 dict보다 더 깊은 경우를 처리하기 위해 를 추가해야합니다 . 답변을 편집하는 것은 좋지만 OP의 문제를 해결하는 간결한 코드를 더럽 히고 싶지는 않습니다.
호브

1
isinstance(v, collections.Mapping)오히려 사용 하지 isinstance(v, dict)? OP가 컬렉션 사용을 시작하기로 결정한 경우?
Matt

2
@Matt Yea 또는 기타 매핑 파생 객체 (사물 목록). 매핑 파생 객체를 조용히 무시하고 업데이트하지 않은 상태로 두는 기능을보다 일반적이고 적게 만듭니다 (OP가 절대로 보거나 잡을 수없는 교묘 한 오류). 거의 항상 매핑을 사용하여 dict 유형을 찾고 기본 문자열을 str 유형을 찾습니다.
호브

2
Python 3+에서 이것을 실행하면로 변경 u.iteritems()됩니다 u.items(). 그렇지 않으면 다음과 같은 상황이 발생합니다.AttributeError: 'dict' object has no attribute 'iteritems'
Greg K

23

이것에 대해 조금 알아 차 렸지만 @Alex의 게시물 덕분에 그는 누락 된 격차를 메 웠습니다. 그러나 재귀 내의 값이 인 경우 문제가 dict발생 list했기 때문에 공유하고 답변을 확장 할 것이라고 생각했습니다.

import collections

def update(orig_dict, new_dict):
    for key, val in new_dict.iteritems():
        if isinstance(val, collections.Mapping):
            tmp = update(orig_dict.get(key, { }), val)
            orig_dict[key] = tmp
        elif isinstance(val, list):
            orig_dict[key] = (orig_dict.get(key, []) + val)
        else:
            orig_dict[key] = new_dict[key]
    return orig_dict

3
아마 이것이 조금 더 안전해야한다고 생각합니다 orig_dict.get(key, []) + val.
Andy Hayden

2
dicts는 변경 가능하므로 전달할 인스턴스를 인수로 변경합니다. 그런 다음 orig_dict를 반환 할 필요가 없습니다.
gabrielhpugliese

3
대부분의 사람들은 정의가 업데이트되었지만 업데이트 된 dict를 반환 할 것으로 기대합니다.
Kel Solaar 2016 년

onosendi 코드의 기본 로직은 업데이트 된 목록을 원본 목록에 추가하는 것입니다. 원래 목록을 덮어 쓰기 업데이트해야하는 경우 설정 orig_dict 필요 [키] = 발
intijk

1
@gabrielhpugliese는 사전 리터럴로 호출 된 경우 원본을 반환해야합니다. 예 : merged_tree = update({'default': {'initialvalue': 1}}, other_tree)
EoghanM

18

@Alex의 대답은 좋지만 정수와 같은 요소를 사전과 같은 사전으로 바꾸면 작동하지 않습니다 update({'foo':0},{'foo':{'bar':1}}). 이 업데이트는 다음을 해결합니다.

import collections
def update(d, u):
    for k, v in u.iteritems():
        if isinstance(d, collections.Mapping):
            if isinstance(v, collections.Mapping):
                r = update(d.get(k, {}), v)
                d[k] = r
            else:
                d[k] = u[k]
        else:
            d = {k: u[k]}
    return d

update({'k1': 1}, {'k1': {'k2': {'k3': 3}}})

내가 참조. elif원래 객체 유형에 대한 검사를 값과 해당 dict / mapping의 키와 검사 모두를 포함하는 "encloing"조건부 로 만들었습니다 . 영리한.
호브

내부 dict에 둘 이상의 키가있는 경우 작동하지 않습니다.
Wlerin

@Wlerin, 여전히 작동합니다. d는 그 시점까지 매핑이 될 것입니다. 여러 키가있는 테스트 사례는 다음과 같습니다 update({'A1': 1, 'A2':2}, {'A1': {'B1': {'C1': 3, 'C2':4}, 'B2':2}, 'A3':5}).. 원하는 것을하지 않는 예가 있습니까?
bscan

if isinstance(d, collections.Mapping)Evey 반복 테스트 가 필요한 이유는 무엇 입니까? 내 답변을 참조하십시오 .
Jérôme

13

허용되는 것과 동일한 솔루션이지만 더 명확한 변수 이름 지정, docstring 및 {}값으로 무시되지 않는 버그가 수정 되었습니다.

import collections


def deep_update(source, overrides):
    """
    Update a nested dictionary or similar mapping.
    Modify ``source`` in place.
    """
    for key, value in overrides.iteritems():
        if isinstance(value, collections.Mapping) and value:
            returned = deep_update(source.get(key, {}), value)
            source[key] = returned
        else:
            source[key] = overrides[key]
    return source

다음은 몇 가지 테스트 사례입니다.

def test_deep_update():
    source = {'hello1': 1}
    overrides = {'hello2': 2}
    deep_update(source, overrides)
    assert source == {'hello1': 1, 'hello2': 2}

    source = {'hello': 'to_override'}
    overrides = {'hello': 'over'}
    deep_update(source, overrides)
    assert source == {'hello': 'over'}

    source = {'hello': {'value': 'to_override', 'no_change': 1}}
    overrides = {'hello': {'value': 'over'}}
    deep_update(source, overrides)
    assert source == {'hello': {'value': 'over', 'no_change': 1}}

    source = {'hello': {'value': 'to_override', 'no_change': 1}}
    overrides = {'hello': {'value': {}}}
    deep_update(source, overrides)
    assert source == {'hello': {'value': {}, 'no_change': 1}}

    source = {'hello': {'value': {}, 'no_change': 1}}
    overrides = {'hello': {'value': 2}}
    deep_update(source, overrides)
    assert source == {'hello': {'value': 2, 'no_change': 1}}

이 기능은의 charlatan 패키지 에서 사용할 수 있습니다 charlatan.utils.


7

누군가가 필요로 할 경우를 대비하여 재귀 사전 병합의 불변 버전이 있습니다.

@Alex Martelli의 답변을 바탕으로 .

파이썬 2.x :

import collections
from copy import deepcopy


def merge(dict1, dict2):
    ''' Return a new dictionary by merging two dictionaries recursively. '''

    result = deepcopy(dict1)

    for key, value in dict2.iteritems():
        if isinstance(value, collections.Mapping):
            result[key] = merge(result.get(key, {}), value)
        else:
            result[key] = deepcopy(dict2[key])

    return result

파이썬 3.x :

import collections
from copy import deepcopy


def merge(dict1, dict2):
    ''' Return a new dictionary by merging two dictionaries recursively. '''

    result = deepcopy(dict1)

    for key, value in dict2.items():
        if isinstance(value, collections.Mapping):
            result[key] = merge(result.get(key, {}), value)
        else:
            result[key] = deepcopy(dict2[key])

    return result

6

깊이가 다른 사전을 업데이트하고 업데이트가 원래 중첩 사전으로 다이빙하는 깊이를 제한 할 수있는 @Alex의 답변 이 약간 개선되었습니다 (업데이트 사전 깊이는 제한되지 않음). 몇 가지 사례 만 테스트되었습니다.

def update(d, u, depth=-1):
    """
    Recursively merge or update dict-like objects. 
    >>> update({'k1': {'k2': 2}}, {'k1': {'k2': {'k3': 3}}, 'k4': 4})
    {'k1': {'k2': {'k3': 3}}, 'k4': 4}
    """

    for k, v in u.iteritems():
        if isinstance(v, Mapping) and not depth == 0:
            r = update(d.get(k, {}), v, depth=max(depth - 1, -1))
            d[k] = r
        elif isinstance(d, Mapping):
            d[k] = u[k]
        else:
            d = {k: u[k]}
    return d

1
감사합니다! 깊이 매개 변수는 어떤 유스 케이스에 적용될 수 있습니까?
Matt

@Matt 알려진 깊이에서 병합 / 업데이트를 원하지 않는 일부 객체 / dict가있는 경우, 새 객체로 덮어 쓰기 만하면됩니다 (예 : 문자열을 딕 트로 바꾸거나 플로트 등으로 받아쓰기)
호브

1
업데이트가 원본보다 최대 1 단계 더 깊은 경우에만 작동합니다. 예를 들어, 이것은 실패합니다 : update({'k1': 1}, {'k1': {'k2': {'k3': 3}}})나는 이것을 해결하는 답변을 추가했습니다
bscan

@bscan 잘 잡아! 그 유스 케이스를 생각하지 않았습니다. 나는 elif 지점에서 더 깊이 재귀를해야한다고 생각합니다. 어떤 아이디어?
호브

if isinstance(d, Mapping)Evey 반복 테스트 가 필요한 이유는 무엇 입니까? 내 답변을 참조하십시오 . (또한 확실하지 않습니다 d = {k: u[k]})
Jérôme

4

이 질문은 오래되었지만 "깊은 병합"솔루션을 검색 할 때 여기에 왔습니다. 위의 답변은 다음과 같은 내용에 영감을주었습니다. 테스트 한 모든 버전에 버그가 있었기 때문에 직접 작성했습니다. 누락 된 임계점은 d [k] 또는 u [k]가 아닌 경우 일부 입력 키의 경우 k에 대한 결정 트리의 임의의 깊이에서 받아쓰기 였습니다.

또한이 솔루션에는 재귀가 필요하지 않습니다. 재귀는 dict.update()작동 방식 과 더 대칭이며을 반환합니다 None.

import collections
def deep_merge(d, u):
   """Do a deep merge of one dict into another.

   This will update d with values in u, but will not delete keys in d
   not found in u at some arbitrary depth of d. That is, u is deeply
   merged into d.

   Args -
     d, u: dicts

   Note: this is destructive to d, but not u.

   Returns: None
   """
   stack = [(d,u)]
   while stack:
      d,u = stack.pop(0)
      for k,v in u.items():
         if not isinstance(v, collections.Mapping):
            # u[k] is not a dict, nothing to merge, so just set it,
            # regardless if d[k] *was* a dict
            d[k] = v
         else:
            # note: u[k] is a dict

            # get d[k], defaulting to a dict, if it doesn't previously
            # exist
            dv = d.setdefault(k, {})

            if not isinstance(dv, collections.Mapping):
               # d[k] is not a dict, so just set it to u[k],
               # overriding whatever it was
               d[k] = v
            else:
               # both d[k] and u[k] are dicts, push them on the stack
               # to merge
               stack.append((dv, v))

4

그냥 python-benedict (I did it) 사용 하십시오. merge(deepupdate) 유틸리티 메소드와 다른 많은 것들이 있습니다. 그것은 python 2 / python 3과 함께 작동하며 잘 테스트되었습니다.

from benedict import benedict

dictionary1=benedict({'level1':{'level2':{'levelA':0,'levelB':1}}})
update={'level1':{'level2':{'levelB':10}}}
dictionary1.merge(update)
print(dictionary1)
# >> {'level1':{'level2':{'levelA':0,'levelB':10}}}

설치: pip install python-benedict

설명서 : https://github.com/fabiocaccamo/python-benedict


2

이 답변들 중 어느 것도 저자는 사전에 저장된 객체를 업데이트하거나 사전 키를 반복하는 개념 (키와 반대)의 개념을 이해하지 못하는 것 같습니다. 그래서 나는 무의미한 타우 톨릭 사전 상점과 검색을하지 않는 것을 작성해야했습니다. dicts는 다른 dicts 또는 simple 유형을 저장한다고 가정합니다.

def update_nested_dict(d, other):
    for k, v in other.items():
        if isinstance(v, collections.Mapping):
            d_v = d.get(k)
            if isinstance(d_v, collections.Mapping):
                update_nested_dict(d_v, v)
            else:
                d[k] = v.copy()
        else:
            d[k] = v

또는 모든 유형으로 작업하는 것이 더 간단합니다.

def update_nested_dict(d, other):
    for k, v in other.items():
        d_v = d.get(k)
        if isinstance(v, collections.Mapping) and isinstance(d_v, collections.Mapping):
            update_nested_dict(d_v, v)
        else:
            d[k] = deepcopy(v) # or d[k] = v if you know what you're doing

2

솔루션을보다 강력하게 만들기 위해 코드의 버그를 수정하기 위해 @Alex Martelli의 답변으로 업데이트하십시오.

def update_dict(d, u):
    for k, v in u.items():
        if isinstance(v, collections.Mapping):
            default = v.copy()
            default.clear()
            r = update_dict(d.get(k, default), v)
            d[k] = r
        else:
            d[k] = v
    return d

핵심은 재귀에서 종종 같은 유형 을 만들고 싶기 때문에 여기서는 사용 v.copy().clear()하지만 사용 하지는 않습니다 {}. 그리고 이것은 dict여기에 collections.defaultdict다른 종류의 default_factorys를 가질 수있는 유형 인 경우에 특히 유용합니다 .

또한 u.iteritems()로 변경 u.items()되었습니다 Python3.


2

@Alex Martelli가 제안한 솔루션을 사용했지만 실패합니다.

TypeError 'bool' object does not support item assignment

두 사전이 어떤 수준에서 데이터 유형이 다른 경우.

같은 수준에서 사전 요소 d는 스칼라 일뿐입니다. Bool사전 요소 u가 여전히 사전 인 경우 사전 이 스칼라로 할당 될 수 없으므로 재 할당이 실패합니다.True[k] .

추가 된 조건 하나는 다음과 같습니다.

from collections import Mapping

def update_deep(d, u):
    for k, v in u.items():
        # this condition handles the problem
        if not isinstance(d, Mapping):
            d = u
        elif isinstance(v, Mapping):
            r = update_deep(d.get(k, {}), v)
            d[k] = r
        else:
            d[k] = u[k]

    return d

2

아래 코드 update({'k1': 1}, {'k1': {'k2': 2}})는 @Alex Martelli의 대답에서 올바른 방법으로 문제를 해결해야합니다 .

def deepupdate(original, update):
    """Recursively update a dict.

    Subdict's won't be overwritten but also updated.
    """
    if not isinstance(original, abc.Mapping):
        return update
    for key, value in update.items():
        if isinstance(value, abc.Mapping):
            original[key] = deepupdate(original.get(key, {}), value)
        else:
            original[key] = value
    return original

1
def update(value, nvalue):
    if not isinstance(value, dict) or not isinstance(nvalue, dict):
        return nvalue
    for k, v in nvalue.items():
        value.setdefault(k, dict())
        if isinstance(v, dict):
            v = update(value[k], v)
        value[k] = v
    return value

사용 dict또는collections.Mapping


1

나는이 질문이 꽤 오래되었다는 것을 알고 있지만 중첩 된 사전을 업데이트해야 할 때 어떻게하는지 게시합니다. 파이썬에서 dicts가 참조로 전달된다는 사실을 사용할 수 있습니다. 키의 경로가 알려져 있고 점으로 구분되어 있다고 가정합니다. data라는 dict가 있다면 Forex :

{
"log_config_worker": {
    "version": 1, 
    "root": {
        "handlers": [
            "queue"
        ], 
        "level": "DEBUG"
    }, 
    "disable_existing_loggers": true, 
    "handlers": {
        "queue": {
            "queue": null, 
            "class": "myclass1.QueueHandler"
        }
    }
}, 
"number_of_archived_logs": 15, 
"log_max_size": "300M", 
"cron_job_dir": "/etc/cron.hourly/", 
"logs_dir": "/var/log/patternex/", 
"log_rotate_dir": "/etc/logrotate.d/"
}

그리고 우리는 큐 클래스를 업데이트하고 싶습니다. 키의 경로는 다음과 같습니다. log_config_worker.handlers.queue.class

다음 함수를 사용하여 값을 업데이트 할 수 있습니다.

def get_updated_dict(obj, path, value):
    key_list = path.split(".")

    for k in key_list[:-1]:
        obj = obj[k]

    obj[key_list[-1]] = value

get_updated_dict(data, "log_config_worker.handlers.queue.class", "myclass2.QueueHandler")

이것은 사전을 올바르게 업데이트합니다.


1

iteritems-Attribute가없는 오늘과 같이 비표준 사전을 우연히 발견했을 수 있습니다. 이 경우 이러한 유형의 사전을 표준 사전으로 쉽게 해석 할 수 있습니다. 예 : Python 2.7 :

    import collections
    def update(orig_dict, new_dict):
        for key, val in dict(new_dict).iteritems():
            if isinstance(val, collections.Mapping):
                tmp = update(orig_dict.get(key, { }), val)
                orig_dict[key] = tmp
            elif isinstance(val, list):
                orig_dict[key] = (orig_dict[key] + val)
            else:
                orig_dict[key] = new_dict[key]
        return orig_dict

    import multiprocessing
    d=multiprocessing.Manager().dict({'sample':'data'})
    u={'other': 1234}

    x=update(d, u)
    x.items()

파이썬 3.8 :

    def update(orig_dict, new_dict):
        orig_dict=dict(orig_dict)
        for key, val in dict(new_dict).items():
            if isinstance(val, collections.abc.Mapping):
                tmp = update(orig_dict.get(key, { }), val)
                orig_dict[key] = tmp
            elif isinstance(val, list):
                orig_dict[key] = (orig_dict[key] + val)
            else:
                orig_dict[key] = new_dict[key]
        return orig_dict

    import collections
    import multiprocessing
    d=multiprocessing.Manager().dict({'sample':'data'})
    u={'other': 1234, "deeper": {'very': 'deep'}}

    x=update(d, u)
    x.items()

0

예! 그리고 또 다른 해결책. 내 솔루션은 확인중인 키가 다릅니다. 다른 모든 솔루션에서는의 키만 봅니다 dict_b. 그러나 여기서 우리는 두 사전의 결합을 봅니다.

당신이 원하는대로 그것을

def update_nested(dict_a, dict_b):
    set_keys = set(dict_a.keys()).union(set(dict_b.keys()))
    for k in set_keys:
        v = dict_a.get(k)
        if isinstance(v, dict):
            new_dict = dict_b.get(k, None)
            if new_dict:
                update_nested(v, new_dict)
        else:
            new_value = dict_b.get(k, None)
            if new_value:
                dict_a[k] = new_value

0

"완전한 중첩 된 사전을 배열로"바꾸려면이 스 니펫을 사용할 수 있습니다.

"old_value"를 "new_value"로 바꿉니다. 사전을 깊이 우선적으로 재구성하고 있습니다. 첫 번째 레벨의 입력 매개 변수로 제공된 List 또는 Str / int에서도 작동 할 수 있습니다.

def update_values_dict(original_dict, future_dict, old_value, new_value):
    # Recursively updates values of a nested dict by performing recursive calls

    if isinstance(original_dict, Dict):
        # It's a dict
        tmp_dict = {}
        for key, value in original_dict.items():
            tmp_dict[key] = update_values_dict(value, future_dict, old_value, new_value)
        return tmp_dict
    elif isinstance(original_dict, List):
        # It's a List
        tmp_list = []
        for i in original_dict:
            tmp_list.append(update_values_dict(i, future_dict, old_value, new_value))
        return tmp_list
    else:
        # It's not a dict, maybe a int, a string, etc.
        return original_dict if original_dict != old_value else new_value

0

재귀를 사용하는 다른 방법 :

def updateDict(dict1,dict2):
    keys1 = list(dict1.keys())
    keys2= list(dict2.keys())
    keys2 = [x for x in keys2 if x in keys1]
    for x in keys2:
        if (x in keys1) & (type(dict1[x]) is dict) & (type(dict2[x]) is dict):
            updateDict(dict1[x],dict2[x])
        else:
            dict1.update({x:dict2[x]})
    return(dict1)

0

새로운 Q 방법 키 체인

dictionary1={'level1':{'level2':{'levelA':0,'levelB':1}},'anotherLevel1':{'anotherLevel2':{'anotherLevelA':0,'anotherLevelB':1}}}
update={'anotherLevel1':{'anotherLevel2':1014}}
dictionary1.update(update)
print dictionary1
{'level1':{'level2':{'levelA':0,'levelB':1}},'anotherLevel1':{'anotherLevel2':1014}}

0

당신은 이것을 시도 할 수 있습니다, 그것은 목록과 함께 작동하며 순수합니다 :

def update_keys(newd, dic, mapping):
  def upsingle(d,k,v):
    if k in mapping:
      d[mapping[k]] = v
    else:
      d[k] = v
  for ekey, evalue in dic.items():
    upsingle(newd, ekey, evalue)
    if type(evalue) is dict:
      update_keys(newd, evalue, mapping)
    if type(evalue) is list:
      upsingle(newd, ekey, [update_keys({}, i, mapping) for i in evalue])
  return newd

0

에 저장되어 있지만 dict 서브 클래스의 객체 유형을 전파하기 위해 로 교체 {}하는 것이 좋습니다 . 예를 들어, 컬렉션과 같은 유형을 유지합니다.type(v)()ud

파이썬 2 :

import collections

def update(d, u):
    for k, v in u.iteritems():
        if isinstance(v, collections.Mapping):
            d[k] = update(d.get(k, type(v)()), v)
        else:
            d[k] = v
    return d

파이썬 3 :

import collections.abc

def update(d, u):
    for k, v in u.items():
        if isinstance(v, collections.abc.Mapping):
            d[k] = update(d.get(k, type(v)()), v)
        else:
            d[k] = v
    return d

-1

그것은 약간 측면이지만 실제로 중첩 된 사전이 필요합니까? 문제에 따라 때로는 평평한 사전으로 충분할 수 있습니다.

>>> dict1 = {('level1','level2','levelA'): 0}
>>> dict1['level1','level2','levelB'] = 1
>>> update = {('level1','level2','levelB'): 10}
>>> dict1.update(update)
>>> print dict1
{('level1', 'level2', 'levelB'): 10, ('level1', 'level2', 'levelA'): 0}

5
중첩 된 구조는 들어오는 json 데이터 셋에서 나온 것이므로 그대로 유지하고 싶습니다.
jay_t

-1

원 라이너를 원한다면 :

{**dictionary1, **{'level1':{**dictionary1['level1'], **{'level2':{**dictionary1['level1']['level2'], **{'levelB':10}}}}}}
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.