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']
Ответ 3
Вам может быть интересно collections.namedtuple
Ответ 4
Если вы правильно поняли, вам нужен объект, где вы можете просто сбросить атрибуты. Если я прав, все, что вам нужно сделать, это создать пустой класс. Например:
>>> class DumpObject: pass
...
>>>#example of usage:
...
>>> a = DumpObject()
>>> a.airspeed = 420
>>> print a.airspeed
420
Что он
Ответ 5
В Python 3. 3+ вы можете использовать SimpleNamespace, который делает именно то, что вы ищете:
from types import SimpleNamespace
obj = SimpleNamespace()
obj.airspeed = 42
https://docs.python.org/3.4/library/types.html#types.SimpleNamespace
Ответ 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']