Python 将类用作数据容器

Python 将类用作数据容器,python,class,dictionary,struct,Python,Class,Dictionary,Struct,有时将相关数据聚集在一起是有意义的。我倾向于用口述,例如 self.group = dict(a=1, b=2, c=3) print self.group['a'] 我的一位同事更喜欢创建一个类 class groupClass(object): def __init__(a, b, c): self.a = a self.b = b self.c = c self.group = groupClass(1, 2, 3) print s

有时将相关数据聚集在一起是有意义的。我倾向于用口述,例如

self.group = dict(a=1, b=2, c=3)
print self.group['a']
我的一位同事更喜欢创建一个类

class groupClass(object):
    def __init__(a, b, c):
        self.a = a
        self.b = b
        self.c = c
self.group = groupClass(1, 2, 3)
print self.group.a
注意,我们没有定义任何类方法

我喜欢使用dict,因为我喜欢最小化代码行数。我的同事认为,如果使用类,代码的可读性会更高,而且将来向类添加方法会更容易


你更喜欢哪一种?为什么?

我更喜欢遵循并使用dict。

在支持dict的语言中,我会使用
结构。字典最接近Python中的结构,至少在我看来是这样


更不用说,如果您真的愿意,您可以向字典中添加方法;)

在我看来,如果你真的从来没有定义过任何类方法,dict或a就更有意义了。简单+内置是好的!不过,每个人都有自己的想法。

我不同意使用一个没有方法的类来提高代码的可读性。您通常期望类提供功能,而不仅仅是数据


因此,我会选择dict,直到功能需求出现,然后类的构造函数可以收到dict:-)

dict显然适合这种情况。它是专门为那个用例设计的。除非您真的打算将该类作为一个类来使用,否则重新设计轮子并招致额外的开销/浪费一个充当坏字典(没有字典功能)的类的空间是没有用的。

您的方式更好。不要试图过多地预测未来,因为你不太可能成功


但是,例如,如果您想识别不同的类型,而不是对所有内容都使用dict。

您可以将dict和class的优点结合在一起,使用从dict继承的一些包装类。您不需要编写样板代码,同时可以使用点表示法

class ObjDict(dict):
    def __getattr__(self,attr):
        return self[attr]
    def __setattr__(self,attr,value):
        self[attr]=value

self.group = ObjDict(a=1, b=2, c=3)
print self.group.a

有一个新的建议,旨在实现你所寻找的东西,叫做。看一看

使用类而不是dict是一种偏好。就我个人而言,我更喜欢在钥匙事先不知道的情况下使用dict。(作为映射容器)

使用类保存数据意味着您可以为类属性提供文档


就我个人而言,也许我使用类的最大原因是利用IDEs自动完成功能!(从技术上讲,这是一个站不住脚的理由,但在实践中非常有用)

背景

R.Hettinger在SF Python的2017年假日会议上介绍了基于属性的可选数据容器的摘要。看看他的和他的。他还在2018年PyCon上发表了关于数据类的演讲

其他数据容器类型在本文中提到,主要在Python3文档中提到(请参见下面的链接)

下面是关于向标准库中添加
recordclass
的邮件列表的讨论

选项

import typing as typ
import collections as ct
import dataclasses as dc


# Problem: You want a simple container to hold personal data.
# Solution: Try a NamedTuple.
>>> class Person(typ.NamedTuple):
...     name: str
...     age: int
>>> a = Person("bob", 30)
>>> a
Person(name='bob', age=30)
标准库中的备选方案

  • :具有属性的元组(请参见seminal)
  • :子类元组(请参见将其与
    namedtuple
    进行比较)
  • :简单类w/可选类声明
  • :只读dict
  • :受约束的相关常量集合(行为类似于类)
  • :具有默认/无样板文件类的可变名称耦合
外部选择

  • :可变名称对偶(另请参见)
  • :将属性访问添加到dicts(SimpleNameSpace的灵感来源于
    SimpleNameSpace
    ;另请参见(py3))
  • :使用功能包装dicts
  • :从映射中访问元素作为键或属性
  • :从容器类中删除样板文件
  • :易变的、类似元组的容器,默认值由E.Smith提供
  • :关于制作自定义结构、对象、束、dict代理等的帖子
哪一个?

决定使用哪个选项取决于具体情况(参见下面的示例)。通常,一个老式的可变字典或不可变名称的tuple就足够了。数据类是最新添加的(Python3.7a),它提供了可变性和可扩展性,并承诺从项目中获得简化的样板文件


示例

import typing as typ
import collections as ct
import dataclasses as dc


# Problem: You want a simple container to hold personal data.
# Solution: Try a NamedTuple.
>>> class Person(typ.NamedTuple):
...     name: str
...     age: int
>>> a = Person("bob", 30)
>>> a
Person(name='bob', age=30)

那么:

如果您希望自动类型转换和自动代码完成(intelli sense):


顺便说一下,我认为Python 3.7 implemented@是将类作为数据容器实现的最简单、最有效的方法

@dataclass
class Data:
    a: list
    b: str    #default variables go after non default variables
    c: bool = False

def func():
    return A(a="hello")

print(func())
输出将是:
hello


它与类似Scala的case类非常相似,是将类用作容器的最简单方法

如果一个人不关心内存占用,那么,或者仅仅是一个带有
\uuuuu插槽的类是很好的选择

但是,如果必须使用几个简单属性创建数百万个对象,则有一种基于库的解决方案:

与类定义相同:

from recordclass import dataobject
class C(dataobject):
    a:int
    b:int
    c:int    
c = C(1, 2, 3)
它有最小的内存占用=
sizeof(PyObject\u HEAD)+3*sizeof(PyObject*)
bytes


为了便于比较,基于
\uuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuu(getters等)我认为这是不必要的。我也可能没有很好地表达他的立场。你的同事应该会觉得有用。相关的post-namedtuple很好;只要记住它们是不可变的。而且不要忘记,如果你以后确实需要添加类方法,你总是可以从namedtuple的结果继承。例如,
class-Point(namedtuple('Point','xy'):…
答案非常好。我选择这个答案是因为我喜欢尝试namedtuple的建议。关于如何将
namedtuple
与OP代码一起使用的示例可能很好。在Pyth中
class Person(Prodict):
    name: str
    email: str
    rate: int

john = Person(name='John', email='john@appleseed.com')
john.rate = 7
john.age = 35  # dynamic
@dataclass
class Data:
    a: list
    b: str    #default variables go after non default variables
    c: bool = False

def func():
    return A(a="hello")

print(func())
from recordclass import make_dataclass
C = make_dataclass("C", ('a', 'b', 'c'))
c = C(1, 2, 3)
from recordclass import dataobject
class C(dataobject):
    a:int
    b:int
    c:int    
c = C(1, 2, 3)