I need a unique (unsigned int) id for my python data class. This is very similar to this so post, but without explicit ctors.
import attr
from attrs import field
from itertools import count
@attr.s(auto_attribs=True)
class Person:
#: each Person has a unique id
_counter: count[int] = field(init=False, default=count())
_unique_id: int = field(init=False)
@_unique_id.default
def _initialize_unique_id(self) -> int:
return next(self._counter)
Is there any more-"pythonic" solution?
Use a default factory instead of just a default. This allows to define a call to get the next id on each instantiation.
A simple means to get a callable that counts up is to use count().__next__
, the equivalent of calling next(...)
on a count
instance.1
The common "no explicit ctor" libraries attr
and dataclasses
both support this:
from itertools import count
from dataclasses import dataclass, field
@dataclass
class C:
identifier: int = field(default_factory=count().__next__)
import attr
@attr.s
class C:
identifier: int = attr.field(factory=count().__next__)
To always use the automatically generated value and prevent passing one in as a parameter, use init=False
.
@dataclass
class C:
identifier: int = field(default_factory=count().__next__, init=False)
1 If one wants to avoid explicitly addressing magic methods, one can use a closure over a count
. For example, factory=lambda counter=count(): next(counter)
.