使类常量谁的类型是它所在的类

问题描述

我有一个带有特殊值“EMPTY”和“UNIVERSE”的 Python 类:

class RealSet:
    """Continuous open,half-open,and closed regions and discreet values of the Reals"""

    # implementation placeholder
    def __init__(self,intervals,*,canonicalize):
        pass

# Outside the class

RealSet.EMPTY = RealSet(tuple(),canonicalize=False)  # type: ignore
RealSet.UNIVERSE = RealSet(((None,None),),canonicalize=False)  # type: ignore

然而,linting、代码完成等不喜欢这样,因为它们不被视为类的静态属性。即使设置它们也会报告为 mypy 错误,因此 # type: ignore.

以下不起作用,因为我无法在类范围内构造 RealSet,因为它尚不存在:

class RealSet:
    """Continuous open,and closed regions and discreet values of the Reals"""
    ...
    ...

    EMPTY = RealSet(tuple(),canonicalize=False)  # error
    UNIVERSE = RealSet(((None,canonicalize=False)  # error

这不起作用,因为它定义了实例属性,而不是类属性

class RealSet:
    """Continuous open,and closed regions and discreet values of the Reals"""
    ...
    ...

    EMPTY: "RealSet"
    UNIVERSE: "RealSet"

# Outside the class

RealSet.EMPTY = RealSet(tuple(),canonicalize=False)
RealSet.UNIVERSE = RealSet(((None,canonicalize=False)

这似乎是 Python 类设计中的一个极端情况。如何创建类属性,其中属性的类型是它所在的类?奖励:使它们保持不变。

解决方法

您可以使用 typing.ClassVar 来注释类变量:

class RealSet:
    def __init__(self,intervals,*,canonicalize):
        pass

    EMPTY: ClassVar['RealSet']
    UNIVERSE: ClassVar['RealSet']


RealSet.EMPTY = RealSet(tuple(),canonicalize=False)
RealSet.UNIVERSE = RealSet(((None,None),),canonicalize=False)
,

从 Python 3.9 开始 classmethod 可以修饰其他描述符,例如 property。这样就可以创建一个“类属性”:

class RealSet:
    def __init__(self,canonicalize):
        pass

    @classmethod
    @property
    def EMPTY(cls):
        return cls(tuple(),canonicalize=False)

    @classmethod
    @property
    def UNIVERSE(cls):
        return cls(((None,canonicalize=False)

相关问答

Selenium Web驱动程序和Java。元素在(x,y)点处不可单击。其...
Python-如何使用点“。” 访问字典成员?
Java 字符串是不可变的。到底是什么意思?
Java中的“ final”关键字如何工作?(我仍然可以修改对象。...
“loop:”在Java代码中。这是什么,为什么要编译?
java.lang.ClassNotFoundException:sun.jdbc.odbc.JdbcOdbc...