JavaScript-подобный объект в стандартной библиотеке Python?

Довольно часто я нахожусь в простом, "дампном" объекте в Python, который ведет себя как объект JavaScript (т.е. к его членам можно получить доступ либо с помощью .member, либо с помощью ['member']).

Обычно я просто вставляю это в начало .py:

class DumbObject(dict):
    def __getattr__(self, attr):
        return self[attr]
    def __stattr__(self, attr, value):
        self[attr] = value

Но такой хромой, и есть хотя бы одна ошибка с этой реализацией (хотя я не могу вспомнить, что это такое).

Итак, есть ли что-то подобное в стандартной библиотеке?

И, для записи, просто instanciating object не работает:

>>> obj = object()
>>> obj.airspeed = 42
Traceback (most recent call last):
  File "", line 1, in 
AttributeError: 'object' object has no attribute 'airspeed'

Изменить: (dang, должен был видеть, как это происходит)... Не волнуйтесь! Я не пытаюсь писать JavaScript в Python. Место, которое я чаще всего нахожу, я хочу, чтобы это было, пока я все еще экспериментирую: у меня есть коллекция "вещей", которая не совсем корректна для ввода словаря, но также не имеет права иметь собственный класс.

Ответы

Ответ 1

Нет никакой "стандартной библиотеки" с этим видом объекта, но на ActiveState существует довольно известный рецепт от Alex Martelli, называемый "bunch" .

Примечание: там также доступен пакет на pypi под названием bunch, и это должно сделать примерно то же самое, но я ничего не знаю о его внедрении и качестве.

Ответ 2

Вы можете попробовать с attrdict:

class attrdict(dict):
    def __init__(self, *args, **kwargs):
        dict.__init__(self, *args, **kwargs)
        self.__dict__ = self

a = attrdict(x=1, y=2)
print a.x, a.y
print a['x'], a['y']

b = attrdict()
b.x, b.y  = 1, 2
print b.x, b.y
print b['x'], b['y']

Ответ 4

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

>>> class DumpObject: pass
... 
>>>#example of usage:
...
>>> a = DumpObject()
>>> a.airspeed = 420
>>> print a.airspeed
420

Что он

Ответ 6

Я не большой поклонник этого, потому что вы попадаете в "что, если вы определяете" ключи ":

foo = DumbObject()
foo.moshe = 'here'
foo.keys # --> gives a callable, if you'll call it you'll get ['moshe']
foo.keys = 'front-door'
foo.keys # --> oh look, now it a string 'front-door'

Являются ли "ключи", предположительно, определенным методом для вашего объекта, или это просто случайность? Если это так, то лучше определить DumbObject как

class DumbObject(object):
    def __init__(self):
        self._dict = {}
    def __getitem__(self, key):
        return self._dict[key]
    __getattr__ = __getitem__
    # Ditto for set
def asDictionary(do):
    return do._dict

Но почему ты это делаешь? Вы уверены, что это правильный ответ? Возможно, вы должны использовать правильный тип объекта?

Ответ 7

Ну, насколько я могу сказать (исправьте меня, если я ошибаюсь), каждый пример здесь не конвертирует вложенные словари в новый тип. Поэтому я сделал этот пример:

class DotDictionary(dict):

def __init__(self, init_value):
    if not isinstance(init_value, dict):
        raise TypeError('Expected dict, got {}'.format(type(init_value)))

    self._dict_to_self(init_value)

def __getattr__(self, name):
    return self[name]

def __setattr__(self, name, val):
    self[name] = val

def __delattr__(self, name):
    del self[name]

def _dict_to_self(self, dct):
    for key, value in dct.items():
        if isinstance(value, dict):
            value = DotDictionary(value)
        if isinstance(value, (tuple, list)):
            for i, _ in enumerate(value):
                if isinstance(value[i], dict):
                    value[i] = DotDictionary(value[i])

        self[key] = value

ideone

Я не уверен на 100%, что он работает абсолютно правильно, поэтому никаких гарантий нет.

Кроме того, возможно, это не pythonic-way, поэтому я готов принять советы.

Ответ 8

Этот метод работает с вложенными словарями и довольно лаконичен.

Во-первых, определите пустой класс. Экземплярам этого класса можно задать любые атрибуты.

class holder:
    pass

Далее просто используйте эту функцию.

def dotted(object):

    if isinstance(object, dict):
        parent = holder()

        for key in object:

            child = object.get(key)
            setattr(parent, key, dotted(child))

        return parent

    return object

Пример использования.

users = dotted(
{
    'john': {
        'fullname': 'John Doe'
        'age': 24,
        'hobbies': [
            'programming',
            'jogging'
        ]
    }
}

users.john.fullname # 'John Doe'
users.john.age # 24
users.john.hobbies # ['programming', 'jogging']