Zaktualizuj wartość zagnieżdżonego słownika o różnej głębokości


162

Szukam sposobu na zaktualizowanie słownika Dict Dictionary1 z zawartością aktualizacji dict bez nadpisywania poziomu A.

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

Wiem, że aktualizacja usuwa wartości na poziomie 2, ponieważ aktualizuje najniższy klucz poziom 1.

Jak mogę sobie z tym poradzić, biorąc pod uwagę, że słownik1 i aktualizacja mogą mieć dowolną długość?


Czy zagnieżdżenie jest zawsze głębokie na trzy poziomy, czy też możesz mieć zagnieżdżenie o dowolnej głębokości?
ChristopheD,

Może mieć dowolną głębokość / długość.
jay_t

Popraw mnie, jeśli się mylę, ale wydaje się, że idealne rozwiązanie wymaga wdrożenia wzorca projektowego kompozytu.
Alexander McNulty,

Odpowiedzi:


263

Odpowiedź @ FM ma właściwą ogólną ideę, tj. Rozwiązanie rekurencyjne, ale nieco osobliwe kodowanie i przynajmniej jeden błąd. Zamiast tego polecam:

Python 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

Python 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

Bug pojawia się, gdy „zmiana” ma k, velement gdzie vjest dicti knie jest pierwotnie kluczowy w słowniku aktualizowany - @ kodem „przeskakuje” FM za tę część aktualizacji (bo wykonuje go na pusty nowy dictktóra nie jest zapisywany ani nigdzie zwracany, po prostu utracony po powrocie wywołania rekurencyjnego).

Moje inne zmiany są drobne: nie ma powodu, aby if/ elseconstruct wykonywała .gettę samą pracę szybciej i czyściej, i isinstancenajlepiej jest stosować ją do abstrakcyjnych klas podstawowych (nie konkretnych) dla uogólnienia.


7
+1 Niezłe złapanie błędu - doh! Pomyślałem, że ktoś będzie miał lepszy sposób na przeprowadzenie isinstancetestu, ale pomyślałem, że się nim zajrzę.
FMc,

6
Kolejna drobna „cecha” powoduje, że to podnosi się, TypeError: 'int' object does not support item assignment.gdy np update({'k1': 1}, {'k1': {'k2': 2}}). Aby zmienić to zachowanie i zamiast tego rozszerzyć zakres słowników, aby zrobić miejsce na głębsze słowniki, możesz dodać znak elif isinstance(d, Mapping):wokół warunku d[k] = u[k]i po nim isinstance. Będziesz także musiał dodać, else: d = {k: u[k]}aby poradzić sobie w przypadku, gdy dyktowanie aktualizacji jest głębsze niż oryginalny dykt. Chętnie edytuję odpowiedź, ale nie chcę brudzić zwięzłego kodu, który rozwiązuje problem OP.
płyty kuchenne

1
Dlaczego warto używać isinstance(v, collections.Mapping)zamiast isinstance(v, dict)? W przypadku, gdy OP zdecyduje się rozpocząć korzystanie z kolekcji?
Matt

2
@Matt Yea lub jakikolwiek inny obiekt wywodzący się z mapowania (listy par elementów). Sprawia, że ​​funkcja jest bardziej ogólna i rzadziej po cichu ignoruje obiekty pochodzące z mapowania i pozostawia je niezaktualizowane (podstępny błąd, którego OP może nigdy nie zobaczyć / złapać). Prawie zawsze chcesz używać mapowania, aby znaleźć typy dict i basestring, aby znaleźć typy str.
płyty grzejne

2
Jeśli używasz tego w Pythonie 3+ zmień u.iteritems()na u.items(), w przeciwnym razie napotkasz:AttributeError: 'dict' object has no attribute 'iteritems'
Greg K,

23

Trochę mi to zajęło, ale dzięki postowi @ Alexa wypełnił lukę, której mi brakowało. Jednak napotkałem problem, jeśli dictzdarza się list, że wartość w rekursywnym jest a , więc pomyślałem, że podzielę się i rozszerzę jego odpowiedź.

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
Myślę, że powinno to prawdopodobnie (być nieco bezpieczniejsze) orig_dict.get(key, []) + val.
Andy Hayden

2
Ponieważ dykty są zmienne, zmieniasz instancję, którą przekazujesz jako argument. Nie musisz wtedy zwracać orig_dict.
gabrielhpugliese

3
Myślę, że większość ludzi spodziewałaby się, że definicja zwróci zaktualizowaną wersję, mimo że jest zaktualizowana.
Kel Solaar,

Domyślną logiką w kodzie onosendi jest dołączanie zaktualizowanej listy do oryginalnej listy. Jeśli chcesz zaktualizować, zastąpić oryginalną listę, musisz ustawić orig_dict [klucz] = val
intijk

1
@gabrielhpugliese zwracanie oryginału jest konieczne, jeśli zostanie wywołane z dosłownym słownikiem, np. merged_tree = update({'default': {'initialvalue': 1}}, other_tree)
EoghanM

18

@ Alex odpowiedź jest dobra, ale nie działa w przypadku zamiany elementu, takiego jak liczba całkowita, na słownik, na przykład update({'foo':0},{'foo':{'bar':1}}). Ta aktualizacja dotyczy tego:

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}}})

Widzę. Zrobiłeś mój elifczek z oryginalnego obiektu wpisać „zamykając” warunkowe zawierające kontrole zarówno wartości i klucz tego dict / mapowania. Sprytny.
płyty grzejne

To nie zadziała, jeśli wewnętrzny dykt ma więcej niż jeden klucz.
Wlerin

@Wlerin, nadal działa; d zostanie w tym momencie mapowaniem. Oto przypadek testowy z wielu kluczy: update({'A1': 1, 'A2':2}, {'A1': {'B1': {'C1': 3, 'C2':4}, 'B2':2}, 'A3':5}). Czy masz przykład, który nie robi tego, co chcesz?
bscan

Po co testować if isinstance(d, collections.Mapping)w każdej iteracji? Zobacz moją odpowiedź .
Jérôme

13

Takie samo rozwiązanie jak przyjęte, ale jaśniejsze nazewnictwo zmiennych, napisy dokumentacyjne i naprawiono błąd, w którym {}wartość nie nadpisywała.

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

Oto kilka przypadków testowych:

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}}

Ta funkcja jest dostępna w pakiecie szarlatan w formaciecharlatan.utils .


7

Oto niezmienna wersja rekurencyjnego scalania słowników na wypadek, gdyby ktoś tego potrzebował.

W oparciu @Alex martelli za odpowiedź .

Python 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

Python 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

Niewielkie ulepszenia odpowiedzi @ Alex, która umożliwia aktualizację słowników o różnych głębokościach, a także ogranicza głębokość, na jaką aktualizacja zagłębia się w oryginalnym zagnieżdżonym słowniku (ale głębokość aktualizacji słownika nie jest ograniczona). Przetestowano tylko kilka przypadków:

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
Dzięki za to! Do jakiego przypadku użycia może mieć zastosowanie parametr depth?
Matt,

@Matt, gdy masz jakieś obiekty / dykty na znanej głębokości, których nie chcesz scalać / aktualizować, po prostu nadpisać nowymi obiektami (jak zastąpienie dyktu ciągiem, pływakiem lub czymkolwiek, głęboko w twoim dyktacie)
płyty grzewcze

1
Działa to tylko wtedy, gdy aktualizacja jest co najwyżej 1 poziom głębsza niż oryginał. Na przykład to się nie udaje: update({'k1': 1}, {'k1': {'k2': {'k3': 3}}})dodałem odpowiedź, która rozwiązuje ten
problem

@bscan dobry chwyt! nigdy nie myślałem o tym przypadku użycia. Myślę, że powinienem powtórzyć głębiej w gałęziach elifów. Jakieś pomysły?
płyty kuchenne

Po co testować if isinstance(d, Mapping)w każdej iteracji? Zobacz moją odpowiedź . (Również nie jestem pewien co do twojego d = {k: u[k]})
Jérôme

4

To pytanie jest stare, ale trafiłem tutaj, szukając rozwiązania „głębokiego scalania”. Powyższe odpowiedzi zainspirowały poniższe. Skończyło się na tym, że napisałem własną, ponieważ we wszystkich testowanych wersjach były błędy. Punktem krytycznym pominiętym było, na jakiejś arbitralnej głębokości dwóch dykt wejściowych, dla jakiegoś klucza k, drzewo decyzyjne, gdy d [k] lub u [k] nie jest dyktem, było błędne.

Ponadto to rozwiązanie nie wymaga rekursji, która jest bardziej symetryczna z tym dict.update(), jak działa, i zwraca 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

Po prostu użyj python-benedict (zrobiłem to) , ma merge(głęboką aktualizację) metodę narzędziową i wiele innych. Działa z pythonem 2 / pythonem 3 i jest dobrze przetestowany.

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}}}

Instalacja: pip install python-benedict

Dokumentacja: https://github.com/fabiocaccamo/python-benedict


2

W żadnej z tych odpowiedzi autorzy nie wydają się rozumieć koncepcji aktualizacji obiektu przechowywanego w słowniku ani nawet iteracji po elementach słownika (w przeciwieństwie do kluczy). Musiałem więc napisać taki, który nie prowadzi do zbędnych magazynów i wyszukiwania w słowniku tautologicznym. Zakłada się, że dykty przechowują inne dykty lub proste typy.

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

Lub jeszcze prostszy pracujący z dowolnym typem:

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

Zaktualizuj odpowiedź @Alex Martelli, aby naprawić błąd w jego kodzie, aby rozwiązanie było bardziej niezawodne:

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

Kluczem jest to, że często chcemy utworzyć ten sam typ przy rekurencji, więc tutaj używamy, v.copy().clear()ale nie {}. Jest to szczególnie przydatne, jeśli dicttutaj jest typ, collections.defaultdictktóry może mieć różne rodzaje default_factory.

Zwróć też uwagę, że u.iteritems()zmieniono na u.items()w Python3.


2

Skorzystałem z rozwiązania, które sugeruje @Alex Martelli, ale zawodzi

TypeError 'bool' object does not support item assignment

kiedy dwa słowniki różnią się na pewnym poziomie typem danych.

W przypadku, gdy na tym samym poziomie element słownika djest po prostu skalarem (tj. Bool), Podczas gdy element słownika ujest nadal słownikiem, ponowne przypisanie nie powiedzie się, ponieważ nie jest możliwe przypisanie słownika do skalarnego (podobnie True[k]).

Jeden dodatkowy warunek rozwiązuje ten problem:

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

Poniższy kod powinien rozwiązać update({'k1': 1}, {'k1': {'k2': 2}})problem w odpowiedzi @Alex Martelli we właściwy sposób.

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

użyj dictlubcollections.Mapping


1

Wiem, że to pytanie jest dość stare, ale nadal publikuję, co robię, gdy muszę zaktualizować zagnieżdżony słownik. Możemy wykorzystać fakt, że dykty są przekazywane przez referencje w pythonie Zakładając, że ścieżka klucza jest znana i jest oddzielona kropkami. Forex jeśli mamy dykt o nazwie dane:

{
"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/"
}

Chcemy zaktualizować klasę kolejki, ścieżka klucza będzie wyglądać następująco: log_config_worker.handlers.queue.class

Aby zaktualizować wartość, możemy skorzystać z następującej funkcji:

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")

Spowoduje to poprawną aktualizację słownika.


1

Może się zdarzyć, że natkniesz się na niestandardowy słownik, taki jak ja dzisiaj, który nie ma iteritems-Attribute. W takim przypadku łatwo jest zinterpretować ten typ słownika jako słownik standardowy. Np .: 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()

Python 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

Tak! I inne rozwiązanie. Moje rozwiązanie różni się kluczami, które są sprawdzane. We wszystkich innych rozwiązaniach patrzymy tylko na klucze dict_b. Ale tutaj patrzymy na połączenie obu słowników.

Zrób to, co chcesz

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

Jeśli chcesz zamienić „pełny słownik zagnieżdżony na tablice”, możesz użyć tego fragmentu:

Zastąpi on każdą „starą wartość” przez „nową_wartość”. Z grubsza polega na przebudowie słownika w pierwszej kolejności. Może nawet działać z listą lub str / int podanym jako parametr wejściowy pierwszego poziomu.

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

Inny sposób wykorzystania rekurencji:

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

nowy Q jak przez breloczek do kluczy

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

możesz spróbować tego, działa z listami i jest czysty:

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

Zalecam zastąpienie {}przez type(v)(), aby propagować typ obiektu dowolnej podklasy dict, która jest przechowywana, uale której nie ma d. Na przykład zachowałoby to typy takie jak kolekcje.

Python 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

Python 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

To trochę na marginesie, ale czy naprawdę potrzebujesz zagnieżdżonych słowników? W zależności od problemu czasami może wystarczyć płaski słownik ... i spójrz na to dobrze:

>>> 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
Zagnieżdżona struktura pochodzi z przychodzących zbiorów danych json, więc chciałbym zachować je nienaruszone, ...
jay_t

-1

Jeśli chcesz mieć jedną linijkę:

{**dictionary1, **{'level1':{**dictionary1['level1'], **{'level2':{**dictionary1['level1']['level2'], **{'levelB':10}}}}}}
Korzystając z naszej strony potwierdzasz, że przeczytałeś(-aś) i rozumiesz nasze zasady używania plików cookie i zasady ochrony prywatności.
Licensed under cc by-sa 3.0 with attribution required.