首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >Python Singleton Dataclass

Python Singleton Dataclass
EN

Stack Overflow用户
提问于 2021-05-11 19:53:01
回答 1查看 2K关注 0票数 4

我有这样一门课:

代码语言:javascript
复制
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的同一个实例。

我可以通过做这样的事情来达到这个目的:

代码语言:javascript
复制
@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
EN

回答 1

Stack Overflow用户

发布于 2022-01-03 01:48:15

我发现实现单例数据的最显着的方法是使用@quamrana注释的回答中建议的单例元类,并添加默认值,以防止打字机在以后不带参数地调用数据集时发出警告。

代码语言:javascript
复制
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方法中设置了适当的值:

代码语言:javascript
复制
@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')

但这只会在运行时引发。

我在你的问题中看到了全局变量。你应该避免使用它。示例(这不是一种处理单例数据集的好方法,只修复示例而不使用全局):

代码语言:javascript
复制
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

票数 0
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/67493491

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档