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

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

当前回答

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__信息。

其他回答

我认为Python结构字典适合这个需求。

d = dict{}
d[field1] = field1
d[field2] = field2
d[field2] = field3

这里有一个快速而肮脏的技巧:

>>> ms = Warning()
>>> ms.foo = 123
>>> ms.bar = 'akafrit'

它是如何工作的?它只是重用内置类警告(从异常派生),并使用它,因为它是你自己定义的类。

优点是您不需要首先导入或定义任何东西,“警告”是一个简短的名称,并且它还清楚地表明您正在做一些肮脏的事情,不应该在其他地方使用,而应该在您的小脚本中使用。

顺便说一下,我试图找到一些更简单的东西,如ms = object(),但不能(最后一个例子是不工作)。如果你有的话,我很感兴趣。

dF:太酷了……我没有 我知道我可以访问的领域 一个使用字典的类。 马克:我希望我遇到的情况 这正是我需要一个元组的时候 但没有什么比 字典。

你可以使用字典访问类的字段,因为类的字段、它的方法和它的所有属性都是用字典存储在内部的(至少在CPython中是这样)。

...这就引出了你的第二个评论。相信Python字典是“沉重的”是一个非常非Python主义的概念。读这样的评论简直要了我的Python禅。这可不太好。

您可以看到,当您声明一个类时,实际上是在为一个字典创建一个相当复杂的包装器——因此,如果有的话,您比使用一个简单的字典增加了更多的开销。顺便说一下,这种开销在任何情况下都是没有意义的。如果您正在处理性能关键的应用程序,请使用C或其他语言。

也许你正在寻找没有构造函数的struct:

class Sample:
  name = ''
  average = 0.0
  values = None # list cannot be initialized here!


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:   # prints 1,2,3 --> OK.
  print v
print "***"
for v in s2.values:   # prints 4 --> OK.
  print v

这里的一些答案非常详尽。我找到的最简单的选项是(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

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