我有这样一门课:
from __future__ import annotations
import os
from dataclasses import dataclass
@dataclass(frozen=True)
class Config:
name: str
age: str
@staticmethod
def init() -> Config:
return Config(
name=...
age=...
)我希望确保init方法总是返回Config的同一个实例。
我可以通过做这样的事情来达到这个目的:
@dataclass(frozen=True)
class Config:
name: str
age: str
@staticmethod
def init() -> Config:
if not _private_instance:
global _private_instance = Config(
name=...
age=...
)
return _private_instance
_private_instance: Optional[Config] = None
But I am wondering if there is a more Pythonic way of doing this. Thanks发布于 2022-01-03 01:48:15
我发现实现单例数据的最显着的方法是使用@quamrana注释的回答中建议的单例元类,并添加默认值,以防止打字机在以后不带参数地调用数据集时发出警告。
from dataclasses import dataclass
class Singleton(type):
_instances = {}
def __call__(cls, *args, **kwargs):
if cls not in cls._instances:
cls._instances[cls] = super().__call__(*args, **kwargs)
return cls._instances[cls]
@dataclass(frozen=True)
class Config(metaclass=Singleton):
name: str = ''
age: str = ''
p1 = Config('John', '25')
print(p1) # Config(name='John', age='25')
p2 = Config()
print(p2) # Config(name='John', age='25')
print(p1 == p2) # True
print(p1 is p2) # True这段代码的唯一问题是,您没有被迫填充dataclass的所有参数。如果这是您希望在打字机上强制执行的内容,请删除默认值,但请注意,如果以后不提供默认值,则会引发警告。或者,您可以检查是否在dunder post_init方法中设置了适当的值:
@dataclass(frozen=True)
class Config(metaclass=Singleton):
name: str = ''
age: str = ''
def __post_init__(self):
if self.name == '' or self.age == '':
raise ValueError('name or age is empty')但这只会在运行时引发。
我在你的问题中看到了全局变量。你应该避免使用它。示例(这不是一种处理单例数据集的好方法,只修复示例而不使用全局):
from __future__ import annotations
from dataclasses import dataclass, field
from typing import Optional
@dataclass(frozen=True)
class Config:
name: str
age: str
_private_instance: Optional[Config] = field(init=False, repr=False)
@classmethod
def init(cls) -> Config:
if not cls._private_instance:
cls._private_instance = Config(
name=...,
age=...,
)
return cls._private_instance另外:您的数据集用于配置,也许您应该考虑库OmegaConf。
https://stackoverflow.com/questions/67493491
复制相似问题