开发者

Is there a data type in Python similar to structs in C++?

Is there a data type in Python similar to structs in C++? I like the struct feat开发者_开发技巧ure myStruct.someName. I know that classes have this, but I don't want to write a class everytime I need a "container" for some data.


Why not? Classes are fine for that.

If you want to save some memory, you might also want to use __slots__ so the objects don't have a __dict__. See http://docs.python.org/reference/datamodel.html#slots for details and Usage of __slots__? for some useful information.

For example, a class holding only two values (a and b) could looks like this:

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

If you actually want a dict but with obj.item access instead of obj['item'], you could subclass dict and implement __getattr__ and __setattr__ to behave like __getitem__ and __setitem__.


In addition to the dict type, there is a namedtuple type that behaves somewhat like a struct.

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

print aStruct.someName, aStruct.anotherName


dataclass is now built-in to Python as of Python 3.7!

from dataclasses import dataclass

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

Test:

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

Output:

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

Besides for the automatic initialization and __repr__ methods which it generates, it also automatically creates an __eq__ method to make it simple and intuitive to compare two instances of the class.

See PEP 557.

Backported to Python 3.6 using the dataclasses package.


Please realise that in C++, the only difference between a class and a struct is that the elements of a class are by default private, as is the inheritance. The following are equivalent:

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

struct D {
    ...
};

In Python, it would make most sense to use a class if you want to use the dot operator to access elements. In fact, it's even easier, as you only have to initialise the members you currently want, and can add/remove members later. Therefore, the following would work:

class D(object):
    pass

You can then add as many members as you want simply by assigning to them.


You can always go for the dynamic approach:

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

This'll make a class with the same methods that you pass in as a dict:

bar = foo(bill="yo",heather="hi",sam="piss off")

leaving you with the following perfectly valid calls on bar:

bar.bill
>> "yo"
bar.heater
>> "hi"

you get the idea...


I believe you're looking for a dict.

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

print d
print d['name']


Try using a dict.

Here's a simplistic demonstration.

>>> something = {}
>>> something['x'] = 42
>>> something['y'] = 'cheese'
>>> something
{'y': 'cheese', 'x': 42}
>>> something['x']
42
>>> something['y']
'cheese'


This may be taking the idea a bit too far, but here's a way to create "structs" using a syntax that's kinda similar to C++ structs that also does some type checking. First, here's an example of using it:

>>> 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)

And here's the implementation. It's a variation of the __slots__ idea where the class with slots (i.e., the "struct" type) is generated dynamically. This could of course be fleshed out in various ways, but this is just a proof of concept.

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))
0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜