gae*_*fan 48 python struct dictionary class
有时将相关数据聚集在一起是有意义的.我倾向于用dict这样做,例如,
self.group = dict(a=1, b=2, c=3)
print self.group['a']
Run Code Online (Sandbox Code Playgroud)
我的一位同事更喜欢创建一个班级
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
Run Code Online (Sandbox Code Playgroud)
请注意,我们没有定义任何类方法.
我喜欢使用dict,因为我喜欢最小化代码行数.我的同事认为如果使用类,代码更具可读性,并且将来更容易向类中添加方法.
你更喜欢哪个?为什么?
pyl*_*ang 29
背景
R. Hettinger在SF Python 2017年假日聚会上介绍了基于属性的替代数据容器的摘要.看他的推文和他的幻灯片.他还在PyCon 2018上就数据类进行了演讲.
本文中提到了其他数据容器类型,主要是Python 3文档(请参阅下面的链接).
以下是关于添加到标准库的python-ideas邮件列表的讨论recordclass.
选项
标准库中的替代品
collections.namedtuple:具有属性的元组(参见精心配方)typing.NamedTuple:sub-classable元组(请参阅此文章将其与之比较namedtuple)types.SimpleNamespace:带有可选类声明的简单类types.MappingProxy:只读字典enum.Enum:约束相关常量的集合(确实表现得像一个类)dataclasses.dataclass:mutable namedtuple with default/boilerplate-less classes外部选项
SimpleNamedspace)哪一个?
决定使用哪个选项取决于具体情况(参见下面的示例).通常一个老式的可变字典或不可变的namedtuple就足够了.数据类是最新增加的(Python 3.7a),提供可变性和可选的不变性,并且受到attrs项目启发的减少样板的承诺.
例子
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)
Run Code Online (Sandbox Code Playgroud)
# Problem: You need to change age each year, but namedtuples are immutable.
# Solution: Use assignable attributes of a traditional class.
>>> class Person:
... def __init__(self, name, age):
... self.name = name
... self.age = age
>>> b = Person("bob", 30)
>>> b.age = 31
>>> b
<__main__.Person at 0x4e27128>
Run Code Online (Sandbox Code Playgroud)
# Problem: You lost the pretty repr and want to add comparison features.
# Solution: Use included repr and eq features from the new dataclasses.
>>> @dc.dataclass(eq=True)
... class Person:
... name: str
... age: int
>>> c = Person("bob", 30)
>>> c.age = 31
>>> c
Person(name='bob', age=31)
>>> d = Person("dan", 31)
>>> c != d
True
Run Code Online (Sandbox Code Playgroud)
小智 6
您可以使用从 dict 继承的一些包装类,将 dict 和 class 的优点结合在一起。您不需要编写样板代码,同时可以使用点表示法。
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
Run Code Online (Sandbox Code Playgroud)
顺便说一句,我认为Python 3.7实现的@ dataclass是将类实现为数据容器的最简单,最有效的方法。
@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())
Run Code Online (Sandbox Code Playgroud)
输出将是:hello
它与Scala之类的案例类太相似,也是将类用作容器的最简单方法。
如果不关心内存占用,那么dict、namedtuple、dataclass或只是一个类__slots__都是不错的选择。
但是,如果必须在有限内存的情况下创建数百万个具有一些简单属性的对象,那么有一种基于recordclass库的解决方案:
from recordclass import make_dataclass
C = make_dataclass("C", ('a', 'b', 'c'))
c = C(1, 2, 3)
Run Code Online (Sandbox Code Playgroud)
与类定义相同:
from recordclass import dataobject
class C(dataobject):
a:int
b:int
c:int
c = C(1, 2, 3)
Run Code Online (Sandbox Code Playgroud)
它具有最小的内存占用=sizeof(PyObject_HEAD) + 3*sizeof(PyObject*)字节。
对于__slots__基于比较的变体需要sizeof(PyGC_Head) + sizeof(PyObject_HEAD) + 3*sizeof(PyObject*)字节。
从 0.15 开始,有一个选项fast_new可以加快实例创建速度:
C = make_dataclass("C", ('a', 'b', 'c'), fast_new=True)
Run Code Online (Sandbox Code Playgroud)
或者
class C(dataobject, fast_new=True):
a:int
b:int
c:int
Run Code Online (Sandbox Code Playgroud)
此选项可将实例创建速度加快两倍。
| 归档时间: |
|
| 查看次数: |
48325 次 |
| 最近记录: |