简体   繁体   English

在Python中动态编辑字典树

[英]Dynamically edit dict tree in Python

I have a piece of PHP code that I am trying to port over to Python that I am unsure how to get working without references. 我有一段PHP代码正在尝试移植到Python,我不确定如何在没有引用的情况下工作。

Essentially it's a config class that works like a tree, each key can have a simple value, or it's own set of keys and values. 本质上,它是一个像树一样工作的配置类,每个键可以有一个简单的值,或者是它自己的一组键和值。 Part of the class requires being able to set one specific part of the tree without having to send an entire new dict for a root key. 类的一部分要求能够设置树的一个特定部分,而不必发送用于根密钥的整个新字典。

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

For example, the above could be a simple configuration. 例如,以上可能是简单的配置。 And calling the below code would change true to false 并调用以下代码会将true更改为false

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

In order to accomplish this in PHP I use references 为了在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;
            }
        }
    }
}

But if I try to do something similar in Python 但是如果我尝试在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

It doesn't work, mData is the right value, but since I have written to it, it is no longer a reference. 它不起作用,mData是正确的值,但是由于我已经写了它,因此它不再是引用。

How can I go about doing this? 我该怎么做呢? Is it even possible in Python, or should I just re-write my logic from scratch and give up on a perfect port? 在Python中甚至可能,还是我应该从头开始重写逻辑并放弃一个完美的端口?

You can make your set method as follows: 您可以如下设置set方法:

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

Though probably it would be better to remove the global value and pass reference to the dict as an argument: 虽然可能最好删除全局值并将引用传递给dict作为参数:

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

I played around with it more and realised I had the solution, I was just applying it improperly. 我更多地尝试了它,并意识到我有解决方案,只是我没有正确地应用它。

Each dictionary, even if it's part of a key of another dictionary, can be passed around by reference. 每个字典,即使它是另一个字典的键的一部分,也可以通过引用传递。 Meaning if I change a key in that dictionary, it will change in the parent as well. 这意味着,如果我更改该词典中的键,其父级中的键也将更改。 Unfortunately I was changing the variable that was a reference to the dictionary, not the dictionary itself. 不幸的是,我更改了引用字典的变量,而不是字典本身。

This works perfectly 这完美地工作

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

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM