Есть ли тип данных в Python, похожий на structs в С++? Мне нравится функция struct myStruct.someName
. Я знаю, что классы имеют это, но я не хочу писать класс каждый раз, когда мне нужен "контейнер" для некоторых данных.
Есть ли тип данных в Python, аналогичный структурам на С++?
Ответ 1
Почему бы и нет? Классы подходят для этого.
Если вы хотите сохранить некоторую память, вы также можете использовать __slots__
, чтобы объекты не имели __dict__
. Подробнее см. http://docs.python.org/reference/datamodel.html#slots и Использование __slots__? для получения некоторой полезной информации.
Например, класс, содержащий только два значения (a
и b
), может выглядеть так:
class AB(object):
__slots__ = ('a', 'b')
Если вы действительно хотите использовать dict, но с obj.item
доступом вместо obj['item']
, вы можете подклассифицировать dict и реализовать __getattr__
и __setattr__
, чтобы вести себя как __getitem__
и __setitem__
.
Ответ 2
В дополнение к типу dict существует тип namedtuple, который ведет себя как структура.
MyStruct = namedtuple('MyStruct', ['someName', 'anotherName'])
aStruct = MyStruct('aValue', 'anotherValue')
print aStruct.someName, aStruct.anotherName
Ответ 3
Помните, что в С++ единственное различие между классом и структурой заключается в том, что элементы класса по умолчанию являются частными, как и наследование. Следующие эквиваленты:
class D : public B {
public:
...
};
struct D {
...
};
В Python было бы разумнее использовать класс, если вы хотите использовать оператор dot для доступа к элементам. На самом деле, это еще проще, поскольку вам нужно только инициализировать членов, которые вы сейчас хотите, и можете добавлять/удалять элементы позже. Поэтому будет работать следующее:
class D(object):
pass
Затем вы можете добавить столько членов, сколько хотите, просто назначив им.
Ответ 4
Вы всегда можете использовать динамический подход:
class foo(object):
def __init__(self,**kwargs):
self.__dict__.update(kwargs)
Это сделает класс с теми же методами, которые вы передадите в качестве dict:
bar = foo(bill="yo",heather="hi",sam="piss off")
оставляя вам следующие полные действительные вызовы на bar
:
bar.bill
>> "yo"
bar.heater
>> "hi"
вы получаете идею...
Ответ 5
Попробуйте использовать dict
.
Вот упрощенная демонстрация.
>>> something = {}
>>> something['x'] = 42
>>> something['y'] = 'cheese'
>>> something
{'y': 'cheese', 'x': 42}
>>> something['x']
42
>>> something['y']
'cheese'
Ответ 6
Я считаю, что вы ищете dict
.
d = dict({
'name': 'myname',
'val': 'myval'
})
print d
print d['name']
Ответ 7
Это может занять слишком немного, но здесь можно создать "структуры", используя синтаксис, похожий на структуры С++, который также выполняет некоторую проверку типов. Во-первых, вот пример его использования:
>>> MyStruct = Struct({
... 'i': int,
... 's': str,
... 'x': float,
... }, 'MyStruct')
>>> print(MyStruct)
MyStruct {
i: int,
s: str,
x: float,
}
>>> instance = MyStruct(i=1, s='s', x=1.0)
>>> print(instance)
MyStruct(i: 1, s: 's', x: 1.0)
И вот реализация. Это вариация идеи __slots__
, в которой класс с слотами (т.е. Тип "struct" ) генерируется динамически. Разумеется, это можно было бы развить разными способами, но это всего лишь доказательство концепции.
class Struct:
class StructInstance:
__slots__ = ()
def __str__(self):
values = []
for name in self.__slots__:
value = getattr(self, name)
values.append('{name}: {value!r}'.format(name=name, value=value))
type_name = self.__class__.__name__
values = ', '.join(values)
return '{type_name}({values})'.format(type_name=type_name, values=values)
def __init__(self, fields, name=None):
for field_name, field_type in fields.items():
assert isinstance(field_name, str), 'Expected str for field name'
assert isinstance(field_type, type), 'Expected type for field type'
self.fields = fields
self.name = name or 'Struct'
self.type = type(
self.name, (self.StructInstance,), {'__slots__': tuple(fields)})
def __call__(self, **values):
instance = self.type()
for name in instance.__slots__:
value = values[name]
expected_type = self.fields[name]
assert isinstance(value, expected_type), 'Expected %s for %s' % (expected_type, name)
setattr(instance, name, value)
return instance
def __str__(self):
fields = [' {n}: {t.__name__},'.format(n=n, t=t) for n, t in self.fields.items()]
return '{name} {{\n{fields}\n}}'.format(name=self.name, fields='\n'.join(fields))