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)