Python:快速和脏数据类型(DTO)

Jo *_* So 17 python dto

很多时候,我发现自己编写了像琐碎的数据类型

class Pruefer:
    def __init__(self, ident, maxNum=float('inf'), name=""):
        self.ident  = ident
        self.maxNum = maxNum
        self.name   = name
Run Code Online (Sandbox Code Playgroud)

虽然这非常有用(显然我不想用匿名的3元组替换上面的内容),但它也是非常有用的.

现在例如,当我想在dict中使用该类时,我必须添加更多类似的样板

    def __hash__(self):
        return hash(self.ident, self.maxNum, self.name)
Run Code Online (Sandbox Code Playgroud)

我承认在我的所有样板类中都可能很难识别出一般模式,但我仍然喜欢这个问题:

  • 在python中是否有任何流行的习惯用来获取带有命名访问器的快速和脏数据类型?

  • 或许如果没有,也许Python大师可能想展示一些元类黑客或类工厂,让我的生活更轻松?

Ale*_*yev 20

>>> from collections import namedtuple
>>> Pruefer = namedtuple("Pruefer", "ident maxNum name")
>>> pr = Pruefer(1,2,3)
>>> pr.ident
1
>>> pr.maxNum
2
>>> pr.name
3
>>> hash(pr)
2528502973977326415
Run Code Online (Sandbox Code Playgroud)

要提供默认值,您需要做更多...简单的解决方案是使用重定义为__new__方法编写子类:

>>> class Pruefer(namedtuple("Pruefer", "ident maxNum name")):
...     def __new__(cls, ident, maxNum=float('inf'), name=""):
...         return super(Pruefer, cls).__new__(cls, ident, maxNum, name)
... 
>>> Pruefer(1)
Pruefer(ident=1, maxNum=inf, name='')
Run Code Online (Sandbox Code Playgroud)


Inf*_*ion 5

Python 3.6中最有前途的事情之一是变量注释。它们允许以以下方式将namedtuple定义为类:

In [1]: from typing import NamedTuple

In [2]: class Pruefer(NamedTuple):
   ...:     ident: int
   ...:     max_num: int
   ...:     name: str
   ...:     

In [3]: Pruefer(1,4,"name")
Out[3]: Pruefer(ident=1, max_num=4, name='name')
Run Code Online (Sandbox Code Playgroud)

与namedtuple相同,但是它保存注释并允许使用某些静态类型分析器(如mypy)检查类型。

更新:15.05.2018

现在,在Python 3.7中提供了数据类,因此这是定义DTO的更好方法,对于向后兼容,您也可以使用attrs库。


pyl*_*ang 5

python 中是否有任何流行的习语来派生快速...具有命名访问器的数据类型?

数据类。他们完成了这个确切的需求。

一些答案提到了数据类,但这里有一个例子。

代码

import dataclasses as dc


@dc.dataclass(unsafe_hash=True)
class Pruefer:
    ident : int
    maxnum : float = float("inf")
    name : str  = ""
Run Code Online (Sandbox Code Playgroud)

演示

pr = Pruefer(1, 2.0, "3")

pr
# Pruefer(ident=1, maxnum=2.0, name='3')

pr.ident
# 1

pr.maxnum
# 2.0

pr.name
# '3'

hash(pr)
# -5655986875063568239
Run Code Online (Sandbox Code Playgroud)

细节

你得到:

  • 漂亮的代表
  • 默认值
  • 散列
  • 虚线属性访问
  • ... 多得多

你不会(直接)得到:

  • 元组解包(与namedtuple不同)

这是有关数据类详细信息的指南