Есть ли тип данных в Python, аналогичный структурам в C ++? - PullRequest
21 голосов
/ 10 мая 2011

Существует ли тип данных в Python, аналогичный структурам в C ++?Мне нравится функция структуры myStruct.someName.Я знаю, что классы имеют это, но я не хочу писать класс каждый раз, когда мне нужен «контейнер» для некоторых данных.

Ответы [ 8 ]

31 голосов
/ 10 мая 2011

Почему бы и нет?Классы подходят для этого.

Если вы хотите сэкономить память, вы также можете использовать __slots__, чтобы объекты не имели __dict__.См. http://docs.python.org/reference/datamodel.html#slots для подробной информации и Использование __slots __? для некоторой полезной информации.

Например, класс, содержащий только два значения (a и b), можетвыглядит следующим образом:

class AB(object):
    __slots__ = ('a', 'b')

Если вы действительно хотите диктовать, но с доступом obj.item вместо obj['item'], вы можете создать подкласс dict и реализовать __getattr__ и __setattr__, чтобы вести себя как__getitem__ и __setitem__.

14 голосов
/ 10 мая 2011

В дополнение к типу dict существует тип namedtuple , который ведет себя как структура.

MyStruct = namedtuple('MyStruct', ['someName', 'anotherName'])
aStruct = MyStruct('aValue', 'anotherValue')

print aStruct.someName, aStruct.anotherName
6 голосов
/ 25 марта 2018

dataclass теперь встроен в Python начиная с Python 3.7!

from dataclasses import dataclass

@dataclass
class EZClass:
    name: str='default'
    qty: int

Тест:

classy = EZClass('cars', 3)
print(classy)

Вывод:

EZClass(name='cars', qty=3)

Кроме методов автоматической инициализации и __repr__, которые он генерирует, он также автоматически создает__eq__ метод, позволяющий сделать простым и интуитивно понятным сравнение двух экземпляров класса.

См. PEP 557 .

Backported в Python 3.6 с использованием классов данных пакет .

6 голосов
/ 10 мая 2011

Пожалуйста, поймите, что в C ++ единственное различие между классом и структурой состоит в том, что элементы класса по умолчанию являются частными, как и наследование.Следующее эквивалентно:

class D : public B {
    public:
    ...
}; 

struct D {
    ...
};

В Python наиболее целесообразно использовать класс, если вы хотите использовать оператор точки для доступа к элементам.На самом деле, это даже проще, так как вам нужно только инициализировать членов, которых вы хотите в данный момент, и позже можно добавлять / удалять участников.Таким образом, будет работать следующее:

class D(object):
    pass

Затем вы можете добавить столько членов, сколько захотите, просто назначив их.

4 голосов
/ 10 мая 2011

Вы всегда можете пойти на динамический подход:

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"

вы получите идею ...

3 голосов
/ 10 мая 2011

Попробуйте использовать dict.

Вот упрощенная демонстрация.

>>> something = {}
>>> something['x'] = 42
>>> something['y'] = 'cheese'
>>> something
{'y': 'cheese', 'x': 42}
>>> something['x']
42
>>> something['y']
'cheese'
2 голосов
/ 10 мая 2011

Я полагаю, вы ищете dict.

d = dict({
        'name': 'myname',
        'val': 'myval'
        })

print d
print d['name']
1 голос
/ 31 октября 2017

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

>>> 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))
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...