Python中的数据类型是否与C ++中的结构相似?

时间:2021-03-29 16:12:28

Is there a data type in Python similar to structs in C++? I like the struct feature 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.

Python中的数据类型是否与C ++中的结构相似?我喜欢结构特征myStruct.someName。我知道类有这个,但我不想每次为某些数据需要一个“容器”时编写一个类。

8 个解决方案

#1


27  

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.

如果要保存一些内存,可能还需要使用__slots__,因此对象没有__dict__。有关__slots__的详细信息和用法,请参阅http://docs.python.org/reference/datamodel.html#slots?一些有用的信息。

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

例如,只包含两个值(a和b)的类可能如下所示:

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__.

如果你真的想要一个dict但是使用obj.item访问而不是obj ['item'],你可以继承dict并实现__getattr__和__setattr__来表现得像__getitem__和__setitem__。

#2


13  

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

除了dict类型之外,还有一个namedtuple类型,其行为有点像struct。

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

print aStruct.someName, aStruct.anotherName

#3


6  

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:

请注意,在C ++中,类和结构之间的唯一区别是类的元素默认是私有的,继承也是如此。以下是等效的:

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:

在Python中,如果要使用点运算符来访问元素,则最有意义的是使用类。事实上,它更容易,因为您只需初始化您当前想要的成员,并可以在以后添加/删除成员。因此,以下方法可行:

class D(object):
    pass

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

然后,您可以根据需要添加任意数量的成员,只需指定它们即可。

#4


5  

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

从Python 3.7开始,dataclass现在内置于Python!

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.

除了它生成的自动初始化和__repr__方法之外,它还自动创建一个__eq__方法,使其比较两个类的实例变得简单直观。

See PEP 557.

见PEP 557。

Backported to Python 3.6 using the dataclasses package.

使用dataclasses包反向移植到Python 3.6。

#5


4  

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:

这将使用与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...

你明白了......

#6


3  

Try using a dict.

尝试使用dict。

Here's a simplistic demonstration.

这是一个简单的演示。

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

#7


2  

I believe you're looking for a dict.

我相信你正在寻找一个字典。

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

print d
print d['name']

#8


1  

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:

这可能会让这个想法有点过分,但是这里有一种方法可以使用类似于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)

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.

这是实施。它是__slots__想法的变体,其中具有槽的类(即“结构”类型)是动态生成的。当然,这可以通过各种方式充实,但这只是概念的证明。

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

#1


27  

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.

如果要保存一些内存,可能还需要使用__slots__,因此对象没有__dict__。有关__slots__的详细信息和用法,请参阅http://docs.python.org/reference/datamodel.html#slots?一些有用的信息。

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

例如,只包含两个值(a和b)的类可能如下所示:

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__.

如果你真的想要一个dict但是使用obj.item访问而不是obj ['item'],你可以继承dict并实现__getattr__和__setattr__来表现得像__getitem__和__setitem__。

#2


13  

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

除了dict类型之外,还有一个namedtuple类型,其行为有点像struct。

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

print aStruct.someName, aStruct.anotherName

#3


6  

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:

请注意,在C ++中,类和结构之间的唯一区别是类的元素默认是私有的,继承也是如此。以下是等效的:

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:

在Python中,如果要使用点运算符来访问元素,则最有意义的是使用类。事实上,它更容易,因为您只需初始化您当前想要的成员,并可以在以后添加/删除成员。因此,以下方法可行:

class D(object):
    pass

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

然后,您可以根据需要添加任意数量的成员,只需指定它们即可。

#4


5  

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

从Python 3.7开始,dataclass现在内置于Python!

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.

除了它生成的自动初始化和__repr__方法之外,它还自动创建一个__eq__方法,使其比较两个类的实例变得简单直观。

See PEP 557.

见PEP 557。

Backported to Python 3.6 using the dataclasses package.

使用dataclasses包反向移植到Python 3.6。

#5


4  

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:

这将使用与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...

你明白了......

#6


3  

Try using a dict.

尝试使用dict。

Here's a simplistic demonstration.

这是一个简单的演示。

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

#7


2  

I believe you're looking for a dict.

我相信你正在寻找一个字典。

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

print d
print d['name']

#8


1  

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:

这可能会让这个想法有点过分,但是这里有一种方法可以使用类似于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)

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.

这是实施。它是__slots__想法的变体,其中具有槽的类(即“结构”类型)是动态生成的。当然,这可以通过各种方式充实,但这只是概念的证明。

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