Рекурсивно доступ dict через атрибуты, а также индексный доступ?

В cpython потоки не выполняются параллельно, поэтому вы должны использовать процессы или асинхронные. Вы можете использовать библиотеку multiprocessing.pool или concurrent.futures.ProcessPoolExecutor, а затем использовать функцию map для выполнения этой функции на всех объектах. Будьте осторожны, если вы установите max_workers равным или большим, чем количество ядер ЦП, которое может возникнуть у других программ.

from concurrent.futures import ProcessPoolExecutor
with ProcessPoolExecutor(max_workers) as executor:
    result =  executor.map(lambda x: x.f(), items)
26
задан 5 revs, 4 users 69% 17 October 2017 в 18:56
поделиться

4 ответа

Вот один из способов создания такого опыта:

class DotDictify(dict):
    MARKER = object()

    def __init__(self, value=None):
        if value is None:
            pass
        elif isinstance(value, dict):
            for key in value:
                self.__setitem__(key, value[key])
        else:
            raise TypeError('expected dict')

    def __setitem__(self, key, value):
        if isinstance(value, dict) and not isinstance(value, DotDictify):
            value = DotDictify(value)
        super(DotDictify, self).__setitem__(key, value)

    def __getitem__(self, key):
        found = self.get(key, DotDictify.MARKER)
        if found is DotDictify.MARKER:
            found = DotDictify()
            super(DotDictify, self).__setitem__(key, found)
        return found

    __setattr__, __getattr__ = __setitem__, __getitem__


if __name__ == '__main__':

    life = {'bigBang':
               {'stars':
                   {'planets': {}  # Value changed from []
                   }
               }
           }

    life = DotDictify(life)
    print(life.bigBang.stars.planets)  # -> []
    life.bigBang.stars.planets.earth = {'singleCellLife' : {}}
    print(life.bigBang.stars.planets)  # -> {'earth': {'singleCellLife': {}}}
47
ответ дан 5 revs, 4 users 67% 28 November 2019 в 07:06
поделиться

Ниже еще одна реализация словаря вложенных атрибутов (вдохновленный ответом Курта Хагенлокера, урезанного до необходимого):

class AttrDict(dict):
    """ Nested Attribute Dictionary

    A class to convert a nested Dictionary into an object with key-values
    accessibly using attribute notation (AttrDict.attribute) in addition to
    key notation (Dict["key"]). This class recursively sets Dicts to objects,
    allowing you to recurse down nested dicts (like: AttrDict.attr.attr)
    """

    def __init__(self, mapping=None):
        super(AttrDict, self).__init__()
        if mapping is not None:
            for key, value in mapping.items():
                self.__setitem__(key, value)

    def __setitem__(self, key, value):
        if isinstance(value, dict):
            value = AttrDict(value)
        super(AttrDict, self).__setitem__(key, value)
        self.__dict__[key] = value  # for code completion in editors

    def __getattr__(self, item):
        try:
            return self.__getitem__(item)
        except KeyError:
            raise AttributeError(item)

    __setattr__ = __setitem__

Это работает как в Python 2, так и в 3:

life = AttrDict({'bigBang': {'stars': {'planets': {}}}})
life['bigBang']['stars']['planets'] = {'earth': {'singleCellLife': {}}}
life.bigBang.stars.planets.earth.multiCellLife = {'reptiles': {}, 'mammals': {}}
print(life.bigBang.stars.planets.earth)
# -> {'singleCellLife': {}, 'multiCellLife': {'mammals': {}, 'reptiles': {}}}

Преобразование KeyError в AttributeError в __getattr__ требуется в Python3 так, чтобы hasattr работал также в случае, если атрибут не найден:

hasattr(life, 'parallelUniverse')
# --> False
3
ответ дан 8 revs, 2 users 98% 28 November 2019 в 07:06
поделиться

Вот еще одно решение:

from typing import Dict, Any

class PropertyTree: pass

def dict_to_prop_tree(yaml_config: Dict[str, Any]) -> PropertyTree:
    tree = PropertyTree()
    for key, value in yaml_config.items():
        if type(value) == dict:
            setattr(tree, key, dict_to_obj_tree(value))
        elif type(value) == list:
            setattr(tree, key, [dict_to_obj_tree(v) for v in value])
        else:
            setattr(tree, key, value)
    return tree

Затем в консоли Python:

d={'a': 1, 'b': 2, 'c': {'d': 4, 'e': 5, 'f': {'g': 6}, 'h': {}, 'j': 7}}
tree=dict_to_prop_tree(d)
tree.a
tree.c.f.g

выводит правильные значения

0
ответ дан Oliver 28 November 2019 в 07:06
поделиться
class AccessMode(dict):
    def __init__(self, mapping = None):
        super(AccessMode, self).__init__()
        if mapping is not None:
            if isinstance(mapping, dict):
                for k, v in mapping.items():
                    if isinstance(v, dict):
                        v = AccessMode(v)
                        self.__setitem__(k, v)
                    else:
                        print "TypeError: Input must be a 'dict' type.\n"

    def __setitem__(self, k, v):
        super(AccessMode, self).__setitem__(k, v)

    def __getitem__(self, k):
        return super(AccessMode,self).__getitem__(k)

    def __missing__(self, k):
        tmp = AccessMode()
        self[k] = tmp
        return tmp 

    __setattr__, __getattr__ = __setitem__, __getitem__
0
ответ дан 2 revs, 2 users 71% 28 November 2019 в 07:06
поделиться
Другие вопросы по тегам:

Похожие вопросы: