7

C-подобные структуры в Python

1

Как можно удобно определить структуру, подобную C, в Python? Я устал постоянно писать подобное:

class MyStruct():
    def __init__(self, field1, field2, field3):
        self.field1 = field1
        self.field2 = field2
        self.field3 = field3

Есть ли более простой и эффективный способ создания такой структуры данных в Python?

5 ответ(ов)

0

Вы, вероятно, ищете структуры без конструкторов. Вот пример, иллюстрирующий это:

class Sample:
    name = ''
    average = 0.0
    values = None  # список нельзя инициализировать здесь!

s1 = Sample()
s1.name = "sample 1"
s1.values = []  # инициализация списка для первого экземпляра
s1.values.append(1)
s1.values.append(2)
s1.values.append(3)

s2 = Sample()
s2.name = "sample 2"
s2.values = []  # инициализация списка для второго экземпляра
s2.values.append(4)

for v in s1.values:   # выводит 1, 2, 3 --> ОК.
    print(v)
print("***")
for v in s2.values:   # выводит 4 --> ОК.
    print(v)

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

0

Вы можете использовать словарь для хранения данных. Например, вы можете определить словарь следующим образом:

myStruct = {'field1': 'некое значение', 'field2': 'другое значение'}

После этого вы сможете работать с его значениями:

print(myStruct['field1'])
myStruct['field2'] = 'какие-то другие значения'

Обратите внимание, что значения в словаре не обязательно должны быть строками. Они могут быть любыми другими объектами.

0

Вы можете обращаться к полям класса, используя словарь, потому что поля класса, его методы и все свойства хранятся внутренне с помощью словарей (по крайней мере, в CPython).

Что касается вашего второго комментария. Вера в то, что словари в Python "тяжеловесные", — это крайне непайтоновское представление. Чтение подобных комментариев убивает мой Python Zen, а это нехорошо.

Когда вы объявляете класс, на самом деле вы создаете довольно сложную обертку вокруг словаря. Таким образом, в этом смысле вы добавляете больше накладных расходов, чем при использовании простого словаря. Накладные расходы, которые, кстати, не имеют значения в любом случае. Если вы работаете над производительными приложениями, используйте C или что-то подобное.

0

Вы также можете передавать параметры инициализации в переменные экземпляра по позициям.

# Абстрактный класс структуры       
class Struct:
    def __init__ (self, *argv, **argd):
        if len(argd):
            # Обновление по словарю
            self.__dict__.update(argd)
        else:
            # Обновление по позициям
            attrs = filter(lambda x: x[0:2] != "__", dir(self))
            for n in range(len(argv)):
                setattr(self, attrs[n], argv[n])

# Конкретный класс
class Point3dStruct(Struct):
    x = 0
    y = 0
    z = 0

pt1 = Point3dStruct()
pt1.x = 10

print(pt1.x)
print("-" * 10)

pt2 = Point3dStruct(5, 6)

print(pt2.x, pt2.y)
print("-" * 10)

pt3 = Point3dStruct(x=1, y=2, z=3)
print(pt3.x, pt3.y, pt3.z)
print("-" * 10)

В этом примере класс Struct предоставляет базовую функциональность для инициализации атрибутов как по позиционным аргументам, так и по ключевым. Класс Point3dStruct наследуется от Struct и имеет три атрибута: x, y и z. Вы можете создать экземпляры этого класса и инициализировать атрибуты как по позициям (в pt2), так и по именам (в pt3).

0

Когда мне нужен "мгновенный объект данных, который также ведет себя как словарь" (Я не думаю о структурах C!), я вспоминаю этот классный хак:

class Map(dict):
    def __init__(self, **kwargs):
        super(Map, self).__init__(**kwargs)
        self.__dict__ = self

Теперь вы можете просто сказать:

struct = Map(field1='foo', field2='bar', field3=42)

self.assertEquals('bar', struct.field2)
self.assertEquals(42, struct['field3'])

Это идеально подходит для случаев, когда вам нужен "мешок данных, который НЕ является классом", и когда именованные кортежи непонятны...

Чтобы ответить на вопрос, пожалуйста, войдите или зарегистрируйтесь