2015-02-23 2 views
0

У меня есть часть PHP-кода, которую я пытаюсь передать на Python, и я не уверен, как работать без ссылок.Динамически редактировать дерево dict в Python

По существу это класс конфигурации, который работает как дерево, каждый ключ может иметь простое значение или собственный набор ключей и значений. Часть класса требует установки одной определенной части дерева без необходимости отправки всего нового dict для корневого ключа.

{ "caching": { "enabled": true }} 

Например, приведенная выше может быть простой конфигурацией. И, подозвав ниже код изменится верно ложному

Config.set('caching:enabled', false); 

Для достижения этой цели в PHP я использовать ссылки

class Config 
{ 
    private static $aValues; 

    public static function set($key, $value) 
    { 
     if(strpos($key, ':')) { 
      $aKeys = explode(':', $key); 
      $iCount = count($aKeys); 
     } else { 
      $aKeys = array($key); 
      $iCount = 1 
     } 

     $mData = &self::$aValues 
     for($i = 0; $i < $iCount; ++$i) 
     { 
      if(!isset($mData[$aKeys[$i])) { 
       $mData[$aKeys[$i]] = array(); 
      } 

      $mData = &$mData[$aKeys[$i]]; 

      if($i == ($iCount - 1)) { 
       $mData = $value; 
      } 
     } 
    } 
} 

Но если я пытаюсь сделать что-то подобное в Python

_dmValues = dict() 

def set(key, value): 
    global _dmValues 

    if key.find(':'): 
     aKey = key.split(':') 
     iCount = len(key) 
    else: 
     aKey = (key,) 
     iCount = 1 

    mData = _dmValues; 
    for i in range(0, iCount): 
     if key[i] not in mData.keys(): 
      mData[key[i]] = dict() 

     mData = mData[key[i]] 

     if i == (iCount - 1): 
      mData = value 

Это не работает, mData - правильное значение, но поскольку я написал ему, он больше не является ссылкой.

Как я могу это сделать? Возможно ли это в Python, или я должен просто переписать свою логику с нуля и отказаться от идеального порта?

+0

Что такое глобальное '_dmValues'? – Marcin

+0

@Marcin это словарь, который является глобальным для модуля. Я исправил этот пример, спасибо, что указали его :) –

ответ

0

я играл вокруг с ним больше и понял, что у меня есть решение, я просто применял его ненадлежащим образом.

Каждый словарь, даже если он является частью ключа другого словаря, может передаваться по ссылке. Если изменить ключ в этом словаре, это изменится и в родительском. К сожалению, я менял переменную, которая была ссылкой на словарь, а не на словарь.

Это отлично работает

mData = _dm_Values 
for i in range(0, iCount): 
    if i == (iCount - 1): 
     mData[key[i]] = value 
    else: 
     if key[i] not in mData.keys(): 
      mData[key[i]] = dict() 
     mData = mData[key[i]] 
0

Вы можете сделать свой метод набора следующим образом:

_dmValues = { "caching": { "enabled": True }} 

def set(key, value): 
    global _dmValues 

    key1,key2 = key.split(':')  

    mData = _dmValues; 

    if key1 in mData: 
     if key2 in mData[key1]: 
      mData[key1][key2] = value 


set('caching:enabled', False) 

print(_dmValues) # {'caching': {'enabled': False}}  

Хотя, вероятно, было бы лучше, чтобы удалить глобальное значение и передать ссылку на Словаре в качестве аргумента:

def set(mData, key, value):  
    key1,key2 = key.split(':')   
    if key1 in mData: 
     if key2 in mData[key1]: 
      mData[key1][key2] = value 


set(_dmValues, 'caching:enabled', False) 

print(_dmValues) # {'caching': {'enabled': False}} 
+0

Извините, но это будет работать только для одного двоеточия. Пример, который я дал, был именно таким, например, строка могла иметь несколько двоеточий и быть на несколько уровней. Кроме того, модуль предназначен только для одного дерева, поэтому не было бы смысла передавать его в любое время. –

Смежные вопросы