Python:数据类的唯一整数?

Python: uniqe integer for dataclass?

我有以下数据class。

@dataclass(frozen=True)
class myDataClass:
    x: float
    y: float

我想要的是,每次我创建这个 class 的对象时,它都会标有一个从 0 开始递增的唯一 ID。

所以,我第一次说 first = myDataClass(0, 1) 那么我应该得到 first.id == 0,然后如果我说 second = myDataClass(0, 1),我应该得到 second.id == 1.

冻结数据类有点棘手,因为您编写的任何动态更新字段的代码都会遇到 FrozenInstanceError,但这当然是可能的:

from dataclasses import dataclass, field

@dataclass(frozen=True)
class myDataClass:
    x: float
    y: float
    id: int = field(init=False)

    def __post_init__(self):
        if not hasattr(myDataClass, "_COUNT"):
            myDataClass._COUNT = 0
        object.__setattr__(self, "id", myDataClass._COUNT)
        myDataClass._COUNT += 1

哪个应该如您所愿:

>>> (myDataClass(1.0,2.0))
myDataClass(x=1.0, y=2.0, id=0)
>>> (myDataClass(1.0,2.0))
myDataClass(x=1.0, y=2.0, id=1)
>>> (myDataClass(1.0,2.0))
myDataClass(x=1.0, y=2.0, id=2)
>>> (myDataClass(1.0,2.0))
myDataClass(x=1.0, y=2.0, id=3)

您可以将 default_factory 用于数据的属性class,并使用 class 变量来跟踪所使用的最大 ID。

from dataclasses import dataclass, field
from typing import ClassVar


def _assign_id():
    new_id = myDataClass._next_id
    myDataClass._next_id += 1
    return new_id


@dataclass(frozen=True)
class myDataClass:
    x: float
    y: float
    id: int = field(default_factory=_assign_id, init=False)
    _next_id: ClassVar[int] = 0

可以通过使用 an itertools.count() instance's __next__ method 作为字段的 default_factory 来生成线程安全的唯一 ID:

from dataclasses import dataclass, field
from itertools import count

@dataclass(frozen=True)
class myDataClass:
    x: float
    y: float
    id: int = field(default_factory=count().__next__, init=False)

它比其他选项更快,不涉及自定义代码,并且至少在 CPython 参考解释器上是线程安全的(itertools.count 在 C 中实现并且不发布 GIL,因此没有两个实例获得相同结果的几率 id).