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

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

当前回答

我发现做到这一点的最好方法是使用自定义字典类,如本文所述:https://stackoverflow.com/a/14620633/8484485

如果需要iPython自动补全支持,只需像这样定义dir()函数:

class AttrDict(dict):
    def __init__(self, *args, **kwargs):
        super(AttrDict, self).__init__(*args, **kwargs)
        self.__dict__ = self
    def __dir__(self):
        return self.keys()

然后像这样定义你的伪结构(这个是嵌套的)

my_struct=AttrDict ({
    'com1':AttrDict ({
        'inst':[0x05],
        'numbytes':2,
        'canpayload':False,
        'payload':None
    })
})

然后你可以像这样访问my_struct中的值:

打印(my_struct.com1.inst)

= > [5]

其他回答

https://stackoverflow.com/a/32448434/159695在Python3中不起作用。

https://stackoverflow.com/a/35993/159695在Python3中工作。

然后我扩展它来添加默认值。

class myStruct:
    def __init__(self, **kwds):
        self.x=0
        self.__dict__.update(kwds) # Must be last to accept assigned member variable.
    def __repr__(self):
        args = ['%s=%s' % (k, repr(v)) for (k,v) in vars(self).items()]
        return '%s(%s)' % ( self.__class__.__qualname__, ', '.join(args) )

a=myStruct()
b=myStruct(x=3,y='test')
c=myStruct(x='str')

>>> a
myStruct(x=0)
>>> b
myStruct(x=3, y='test')
>>> c
myStruct(x='str')

我在这里没有看到这个答案,所以我想我将添加它,因为我现在正在学习Python,并且刚刚发现它。Python教程(在本例中是Python 2)给出了以下简单而有效的示例:

class Employee:
    pass

john = Employee()  # Create an empty employee record

# Fill the fields of the record
john.name = 'John Doe'
john.dept = 'computer lab'
john.salary = 1000

也就是说,创建一个空类对象,然后实例化,动态添加字段。

这样做的好处是非常简单。缺点是它不是特别自记录的(在类“定义”中没有列出预期的成员),并且未设置字段在访问时可能会导致问题。这两个问题可以通过以下方法解决:

class Employee:
    def __init__ (self):
        self.name = None # or whatever
        self.dept = None
        self.salary = None

现在,您至少可以一目了然地看到程序将期望哪些字段。

两者都很容易打错别字,约翰。Slarly = 1000将成功。不过,它还是有效的。

还可以按位置将初始化参数传递给实例变量

# Abstract struct class       
class Struct:
    def __init__ (self, *argv, **argd):
        if len(argd):
            # Update by dictionary
            self.__dict__.update (argd)
        else:
            # Update by position
            attrs = filter (lambda x: x[0:2] != "__", dir(self))
            for n in range(len(argv)):
                setattr(self, attrs[n], argv[n])

# Specific class
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

NamedTuple很舒服。但是没有人共享性能和存储。

from typing import NamedTuple
import guppy  # pip install guppy
import timeit


class User:
    def __init__(self, name: str, uid: int):
        self.name = name
        self.uid = uid


class UserSlot:
    __slots__ = ('name', 'uid')

    def __init__(self, name: str, uid: int):
        self.name = name
        self.uid = uid


class UserTuple(NamedTuple):
    # __slots__ = ()  # AttributeError: Cannot overwrite NamedTuple attribute __slots__
    name: str
    uid: int


def get_fn(obj, attr_name: str):
    def get():
        getattr(obj, attr_name)
    return get
if 'memory test':
    obj = [User('Carson', 1) for _ in range(1000000)]      # Cumulative: 189138883
    obj_slot = [UserSlot('Carson', 1) for _ in range(1000000)]          # 77718299  <-- winner
    obj_namedtuple = [UserTuple('Carson', 1) for _ in range(1000000)]   # 85718297
    print(guppy.hpy().heap())  # Run this function individually. 
    """
    Index  Count   %     Size   % Cumulative  % Kind (class / dict of class)
     0 1000000    24 112000000 34 112000000  34 dict of __main__.User
     1 1000000    24 64000000  19 176000000  53 __main__.UserTuple
     2 1000000    24 56000000  17 232000000  70 __main__.User
     3 1000000    24 56000000  17 288000000  87 __main__.UserSlot
     ...
    """

if 'performance test':
    obj = User('Carson', 1)
    obj_slot = UserSlot('Carson', 1)
    obj_tuple = UserTuple('Carson', 1)

    time_normal = min(timeit.repeat(get_fn(obj, 'name'), repeat=20))
    print(time_normal)  # 0.12550550000000005

    time_slot = min(timeit.repeat(get_fn(obj_slot, 'name'), repeat=20))
    print(time_slot)  # 0.1368690000000008

    time_tuple = min(timeit.repeat(get_fn(obj_tuple, 'name'), repeat=20))
    print(time_tuple)  # 0.16006120000000124

    print(time_tuple/time_slot)  # 1.1694481584580898  # The slot is almost 17% faster than NamedTuple on Windows. (Python 3.7.7)

如果你的__dict__没有被使用,请在__slots__(更高的性能和存储)和NamedTuple(清晰的阅读和使用)之间选择。

您可以查看此链接(插槽的使用 )来获取更多的__slots__信息。

你可以用元组来做很多你在C语言中使用结构体的事情(比如x,y坐标或RGB颜色)。

对于其他任何东西,你可以使用字典,或像这样的实用程序类:

>>> class Bunch:
...     def __init__(self, **kwds):
...         self.__dict__.update(kwds)
...
>>> mystruct = Bunch(field1=value1, field2=value2)

我认为“权威”的讨论在这里,在Python Cookbook的出版版本中。