python - Python : prohibit instantiation 中没有抽象方法的抽象数据类

标签 python python-3.x oop abc python-dataclasses

即使一个类是从 ABC 继承的, 看起来它仍然可以实例化,除非它包含抽象方法。

有了下面的代码,防止 Identifier 的最佳方法是什么?创建对象:Identifier(['get', 'Name']) ?

from abc import ABC
from typing import List
from dataclasses import dataclass

@dataclass
class Identifier(ABC):
    sub_tokens: List[str]

    @staticmethod
    def from_sub_tokens(sub_tokens):
        return SimpleIdentifier(sub_tokens) if len(sub_tokens) == 1 else CompoundIdentifier(sub_tokens)


@dataclass
class SimpleIdentifier(Identifier):
    pass


@dataclass
class CompoundIdentifier(Identifier):
    pass

如果这个问题已经得到回答,我提前道歉。这看起来很基本,但是,由于某种原因我找不到答案。

干杯,赫利卜。

最佳答案

您可以创建一个 AbstractDataclass保证这种行为的类,并且每次遇到您描述的情况时都可以使用它。

@dataclass 
class AbstractDataclass(ABC): 
    def __new__(cls, *args, **kwargs): 
        if cls == AbstractDataclass or cls.__bases__[0] == AbstractDataclass: 
            raise TypeError("Cannot instantiate abstract class.") 
        return super().__new__(cls)

所以,如果 Identifier继承自 AbstractDataclass而不是来自 ABC直接修改__post_init__将不需要。
@dataclass
class Identifier(AbstractDataclass):
    sub_tokens: List[str]

    @staticmethod
    def from_sub_tokens(sub_tokens):
        return SimpleIdentifier(sub_tokens) if len(sub_tokens) == 1 else CompoundIdentifier(sub_tokens)


@dataclass
class SimpleIdentifier(Identifier):
    pass


@dataclass
class CompoundIdentifier(Identifier):
    pass

实例化 Identifier会养TypeError但没有实例化 SimpleIdentifierCompountIdentifier .
AbstractDataclass可以在代码的其他部分重用。

关于python - Python : prohibit instantiation 中没有抽象方法的抽象数据类,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/60590442/

相关文章:

python - 如何将 raw_input 重定向到 stderr 而不是 stdout?

python - 无法导入咖啡

python - 使用 "while"从另一个列表中删除一个列表的元素

sql - 这是一个好的设计吗?

Pythonic 嵌套 for - Python 中的循环

python - 将 2d numpy 数组与其自身进行比较以形成 3d 数组

python - Django:获取每个用户的发票、费用、提款。 (ORM) 关系

python-3.x - 类型错误 : predict() got an unexpected keyword argument 'callbacks'

python - 避免数组迭代中的跳行

linux - 导致内核崩溃的 Perl 脚本