Как преобразовать производный рекурсивный тип данных в базовый тип данных? - PullRequest
0 голосов
/ 14 декабря 2010

У меня есть класс nesteddict, полученный из коллекций collection.defaultdict, который содержит вложенный набор словарей:

import collections

class nesteddict(collections.defaultdict):
    """Nested dictionary structure.

    Based on Stack Overflow question 635483
    """
    def __init__(self):
        collections.defaultdict.__init__(self, nesteddict)
        self.locked = False

Я хотел бы иметь возможность выполнить операцию, экземпляр которой преобразует все объекты nesteddictк python-native объектам dict.

Один из способов сделать это состоит в том, чтобы иметь метод:

def todict(self):
    for (key,val) in self.iteritems():
        if isinstance(val,nesteddict):
            val.todict()
            self[key] = dict(val)
    self = dict(self)

Это успешно при замене всех внутренних объектов отображения на типы dict, но последнийоператор в методе, очевидно, не будет работать.

Вот пример:

In [93]: a = pyutils.nesteddict()

In [94]: a[1][1] = 'a'

In [95]: a[1][2] = 'b'

In [96]: a[2][1] = 'c'

In [97]: a[2][2] = 'd'

In [98]: print a
defaultdict(<class 'pyutils.nesteddict'>, {1: defaultdict(<class 'pyutils.nesteddict'>, {1: 'a', 2: 'b'}), 2: defaultdict(<class 'pyutils.nesteddict'>, {1: 'c', 2: 'd'})})

In [99]: a.todict()

In [100]: print a
defaultdict(<class 'pyutils.nesteddict'>, {1: {1: 'a', 2: 'b'}, 2: {1: 'c', 2: 'd'}})

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

Спасибо!
Uri

Ответы [ 4 ]

5 голосов
/ 14 декабря 2010

Сделайте это как бесплатную функцию, и пока вы занимаетесь этим, рассмотрите более функциональный стиль:

def undefaulted(x):
  return dict(
    (k, undefaulted(v))
    for (k, v) in x.iteritems()
  ) if isinstance(x, nesteddict) else x

a = undefaulted(a)
3 голосов
/ 24 октября 2012

Я только что столкнулся с этой проблемой сам, используя вложенные defaultdicts. Мое решение:

def dictify(d):
    return {k:dictify(v) for k,v in d.items()} if \
        isinstance(d,nesteddict) else d

Лучше использовать {}, чем dict (), потому что вызов конструктор dict () ограничивает количество аргументов ключевого слова 255. См .: Каково максимальное количество аргументов в функции Python?

1 голос
/ 14 декабря 2010

dict(a) даст вам диктант по умолчанию для любого объекта, который происходит от defaultdict.То есть, если вы не изменили требуемые специальные методы.

0 голосов
/ 14 декабря 2010

Первое, что я заметил в вашем коде, это то, что вы изменяете (или пытаетесь) переменную self.Эта переменная просто указывает на текущий экземпляр вашего класса.Если вы переназначаете его, вы просто указываете его на другое значение, но предыдущее значение, обозначенное self, остается неизменным.Вот как работает Python.

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

def anothertodict(self):
    stuff = dict(self)
    for (key,val) in stuff.iteritems():
        if isinstance(val,nesteddict):
            stuff[key] = val.anothertodict()
    return stuff

Таким образом, есливы делаете: print a.anothertodict() вы получите то, что ожидаете получить.

PS: Зачем вам нужно конвертировать из defaultdict в dict?

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...