是否有一种方法可以方便地在Python中定义类c结构?我厌倦了写这样的东西:

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

当前回答

更新:数据类

随着Python 3.7中数据类的引入,我们已经非常接近了。

下面的示例与下面的NamedTuple示例类似,但是生成的对象是可变的,并且允许使用默认值。

from dataclasses import dataclass


@dataclass
class Point:
    x: float
    y: float
    z: float = 0.0


p = Point(1.5, 2.5)

print(p)  # Point(x=1.5, y=2.5, z=0.0)

如果您想使用更特定的类型注释,这可以很好地配合新的类型模块。

我一直在绝望地等待这一刻!要我说,Data Classes和新的NamedTuple声明,再加上typing模块,简直就是天赐之物!

改进的NamedTuple声明

自从Python 3.6以来,它变得非常简单和美丽(恕我直言),只要你能忍受不变性。

引入了一种声明NamedTuples的新方法,它也允许类型注释:

from typing import NamedTuple


class User(NamedTuple):
    name: str


class MyStruct(NamedTuple):
    foo: str
    bar: int
    baz: list
    qux: User


my_item = MyStruct('foo', 0, ['baz'], User('peter'))

print(my_item) # MyStruct(foo='foo', bar=0, baz=['baz'], qux=User(name='peter'))

其他回答

一本字典怎么样?

就像这样:

myStruct = {'field1': 'some val', 'field2': 'some val'}

然后你可以使用这个来操作值:

print myStruct['field1']
myStruct['field2'] = 'some other values'

值不一定是字符串。它们可以是其他任何物体。

就我个人而言,我也喜欢这种变体。它扩展了@dF的答案。

class struct:
    def __init__(self, *sequential, **named):
        fields = dict(zip(sequential, [None]*len(sequential)), **named)
        self.__dict__.update(fields)
    def __repr__(self):
        return str(self.__dict__)

它支持两种初始化模式(可以混合使用):

# Struct with field1, field2, field3 that are initialized to None.
mystruct1 = struct("field1", "field2", "field3") 
# Struct with field1, field2, field3 that are initialized according to arguments.
mystruct2 = struct(field1=1, field2=2, field3=3)

而且,它打印得更好:

print(mystruct2)
# Prints: {'field3': 3, 'field1': 1, 'field2': 2}

您可以子类化标准库中可用的C结构。ctypes模块提供了一个Structure类。文档中的例子:

>>> from ctypes import *
>>> class POINT(Structure):
...     _fields_ = [("x", c_int),
...                 ("y", c_int)]
...
>>> point = POINT(10, 20)
>>> print point.x, point.y
10 20
>>> point = POINT(y=5)
>>> print point.x, point.y
0 5
>>> POINT(1, 2, 3)
Traceback (most recent call last):
  File "<stdin>", line 1, in ?
ValueError: too many initializers
>>>
>>> class RECT(Structure):
...     _fields_ = [("upperleft", POINT),
...                 ("lowerright", POINT)]
...
>>> rc = RECT(point)
>>> print rc.upperleft.x, rc.upperleft.y
0 5
>>> print rc.lowerright.x, rc.lowerright.y
0 0
>>>

更新:数据类

随着Python 3.7中数据类的引入,我们已经非常接近了。

下面的示例与下面的NamedTuple示例类似,但是生成的对象是可变的,并且允许使用默认值。

from dataclasses import dataclass


@dataclass
class Point:
    x: float
    y: float
    z: float = 0.0


p = Point(1.5, 2.5)

print(p)  # Point(x=1.5, y=2.5, z=0.0)

如果您想使用更特定的类型注释,这可以很好地配合新的类型模块。

我一直在绝望地等待这一刻!要我说,Data Classes和新的NamedTuple声明,再加上typing模块,简直就是天赐之物!

改进的NamedTuple声明

自从Python 3.6以来,它变得非常简单和美丽(恕我直言),只要你能忍受不变性。

引入了一种声明NamedTuples的新方法,它也允许类型注释:

from typing import NamedTuple


class User(NamedTuple):
    name: str


class MyStruct(NamedTuple):
    foo: str
    bar: int
    baz: list
    qux: User


my_item = MyStruct('foo', 0, ['baz'], User('peter'))

print(my_item) # MyStruct(foo='foo', bar=0, baz=['baz'], qux=User(name='peter'))

这里的一些答案非常详尽。我找到的最简单的选项是(from: http://norvig.com/python-iaq.html):)

class Struct:
    "A structure that can have any fields defined."
    def __init__(self, **entries): self.__dict__.update(entries)

初始化:

>>> options = Struct(answer=42, linelen=80, font='courier')
>>> options.answer
42

添加更多的:

>>> options.cat = "dog"
>>> options.cat
dog

编辑:对不起,没有看到这个例子已经进一步。