Подобный JavaScript объект в стандартной библиотеке Python? - PullRequest
20 голосов
/ 15 апреля 2010

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

Обычно я просто прикрепляю это наверху .py:

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

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

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

И, к сведению, простое создание экземпляра object не работает:

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

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

Ответы [ 7 ]

12 голосов
/ 15 апреля 2010

Вы можете попробовать с 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']
8 голосов
/ 15 апреля 2010

Вас может заинтересовать collections.namedtuple

7 голосов
/ 15 апреля 2010

Не существует «стандартной библиотеки» с такими объектами, но в ActiveState есть довольно известный рецепт от Алекса Мартелли, называемый «Связка» .

Примечание: на pypi есть также пакет, называемый Связка , который должен делать то же самое, но я ничего не знаю о его реализации и качестве.

6 голосов
/ 15 апреля 2010

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

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

Вот и все

3 голосов
/ 19 февраля 2019

В Python 3.3+ вы можете использовать SimpleNamespace, который делает именно то, что вы ищете:

from types import SimpleNamespace
obj = SimpleNamespace()
obj.airspeed = 42

https://docs.python.org/3.4/library/types.html#types.SimpleNamespace

1 голос
/ 29 июля 2015

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

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%, что он работает абсолютно корректно, поэтому здесь никаких гарантий.

Также, возможно, это не питон, поэтому я готов принять совет.

1 голос
/ 15 апреля 2010

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

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's 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

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

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