2014-02-17 5 views
7

Мне нужно определить кучу гибких структур (объекты с простой коллекцией именованных полей, где вы можете добавлять новые поля позже, но мне не нужны методы или наследование или что-то в этом роде) в Python 2,7. (Контекст состоит в том, что я читаю материал из двоичных файлов с помощью struct.unpack_from, а затем добавляю дополнительные данные к результатам.)Конкретная гибкая структура определения

Класс отвечает требованиям, например.

class Thing: 
    def __init__(self, foo, bar): 
     self.foo = foo 
     self.bar = bar 

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

Есть ли способ получить гибкость класса, по крайней мере, из краткости коллекций. Namedtuple?

+2

Есть вы считали, что используете dicts? –

ответ

6

Спрятанный в argparse модуля Namespace:

from argparse import Namespace 

n = Namespace(foo='Foo', bar='Bar') 

n 
Out[3]: Namespace(bar='Bar', foo='Foo') 

n.bar 
Out[4]: 'Bar' 

n.hey = 'Hey' 

n 
Out[6]: Namespace(bar='Bar', foo='Foo', hey='Hey') 
+0

Обратите внимание, что в python3.3 + существует 'types.SimpleNamespace'. Это более интуитивно понятно, потому что вы не ожидаете необходимости 'argparse', если вы не разбираете командные строки. – Bakuriu

7

Узор, который я нашел иногда полезен

class Obj(object): 
    def __init__(self, **kwargs): 
     self.__dict__.update(kwargs) 

и вы можете использовать его как

p = Obj(x=10, y=20) 
0

Что-то я написал для этой цели:

def initialize(instance, args): 
    """ 
    In __init__, call initialize(self, locals()) to load all passed 
    arguments. 
    """ 
    if 'self' in args: 
     del args['self'] 
    for k, v in args.items(): 
     setattr(instance, k, v) 

class MyClass: 
    def __init__(self, a, b, c): 
     initialize(self, locals()) 

a = MyClass(1, 2, 3) 

Однако, в конце концов, я решил, что отсутствие читаемости, вызванное этим, не стоило сэкономить нажатия клавиш, это не было для меня особенно большой проблемой.

0

Есть ли способ получить гибкость класса, по крайней мере, с некоторыми из краткости коллекций.namedtuple?

Просто используйте свой класс и дать ему атрибуты класса:

class Namespace(object): 
    foo = 'bar' 

и теперь, Namespace.foo возвращается 'bar'

Плохой стиль в сценарии, но в оболочке, вы можете установить несколько атрибутов, разделенных точкой с запятой:

>>> class NameSpace(object): foo = 'bar'; baz = {} 
>>> NameSpace.baz['quux'] = 'ni' 
>>> NameSpace.foo 
'bar' 
>>> NameSpace.something = 'completely different' 

... collections.namedtuple?

Ну, выше, еще более кратким, но ниже немного больше похож на collections.namedtuple, (заставляет вас задаться вопросом, где они получили эту идею, не так ли?):

>>> NameSpace = type('NameSpace', (object,), {'foo': 'bar', 'baz': {}}) 
>>> NameSpace.baz['quux'] = 'ni' 
>>> NameSpace.foo 
'bar' 
Смежные вопросы