数据类中的auto()类似于Enum(Python)中的自动()



是否有方法使用Dataclass而不是Enum来执行下面的相同代码?

from enum import Enum, auto

class State(Enum):
val_A= auto()
val_B = auto()
val_C = auto()

我找到的唯一解决方案是以下代码:

from dataclasses import dataclass
@dataclass(frozen=True)
class State():
val_A:str = 'val_A'
val_B:str = 'val_B'
val_C:str = 'val_C'

谢谢你的建议。

描述符

一种方法可以是使用描述符类,定义如下:

class Auto:
_GLOBAL_STATE = {}
__slots__ = ('_private_name', )
# `owner` is the class or type, whereas instance is an object of `owner`
def __get__(self, instance, owner):
try:
return getattr(instance, self._private_name)
except AttributeError:
_state = self.__class__._GLOBAL_STATE
_dflt = _state[owner] = _state.get(owner, 0) + 1
return _dflt
def __set_name__(self, owner, name):
self._private_name = '_' + name
def __set__(self, instance, value):
# use object.__setattr__() instead of setattr() as dataclasses
# also does, in case of a "frozen" dataclass
object.__setattr__(instance, self._private_name, value)

用法如下:

from dataclasses import dataclass

@dataclass(frozen=True)
class State:
val_A: int = Auto()
val_B: int = Auto()
val_C: int = Auto()

s = State()
print(s)  # State(val_A=1, val_B=2, val_C=3)
assert s.val_B == 2
s = State(val_A=5)
assert s.val_A == 5
assert s.val_C == 3

最佳方法

我能想到的性能最好的方法是在dataclasses能够处理类之前替换默认值。

最初这是O(N)时间,因为它需要对所有类成员(包括dataclass字段(至少迭代一次。然而,真正的好处是,在@dataclass装饰器能够处理类之前,它替换了auto值的默认值,例如val_A: int = 1

例如,定义一个元类,如下所示:

# sentinel value to detect when to replace a field's default
auto = object()

def check_auto(name, bases, cls_dict):
default = 1
for name, val in cls_dict.items():
if val == auto:
cls_dict[name] = default
default += 1
cls = type(name, bases, cls_dict)
return cls

用法如下:

from dataclasses import dataclass

@dataclass(frozen=True)
class State(metaclass=check_auto):
val_A: int = auto
val_B: int = auto
val_C: int = auto

s = State()
print(s)  # State(val_A=1, val_B=2, val_C=3)
assert s.val_B == 2
s = State(val_A=5)
assert s.val_A == 5
assert s.val_C == 3

最新更新