如何实例化作为类实例的类变量?

时间:2020-03-26 00:31:26

标签: python-3.x

我有一个Vector2类,我想定义一些Vector2作为类变量,即unit up,unit right,zero等。但是,以下代码坚持未定义Vector2。

from collections import deque,namedtuple
from typing import ClassVar

@dataclass
class Vector2:
    UNIT_UP    : ClassVar = Vector2(0,1)
    UNIT_DOWN  : ClassVar = Vector2(0,-1)
    UNIT_LEFT  : ClassVar = Vector2(-1,0)
    UNIT_RIGHT : ClassVar = Vector2(1,0)
    ZERO       : ClassVar = __class__(0,0) # this approach doesn't work either

    x : int = 0
    y : int = 0

    # some math dunders

1 个答案:

答案 0 :(得分:2)

您无法在自己的主体中创建类的实例,因为主体需要先完成运行,然后才能创建类对象。类主体运行所在的名称空间将成为类名称空间。

要执行所需的操作,需要首先创建类,然后再分配类属性。您可能完全不需要在类中添加任何有关属性的细节就可以做到这一点:

class Foo:
   pass

Foo.SOME_INSTANCE = Foo()

这也将与您的数据类一起很好地工作,但是由于我们已经删除了类变量的类型注释,因此对静态类型检查器的友好程度可能不如您所愿。如果愿意,可以将ClassVar的类型注释保留在类中,但随后将它们的值初始化:

@dataclass
class Vector2:
    UNIT_UP    : ClassVar['Vector2']
    UNIT_DOWN  : ClassVar['Vector2']
    UNIT_LEFT  : ClassVar['Vector2']
    UNIT_RIGHT : ClassVar['Vector2']
    ZERO       : ClassVar['Vector2']

    x : int = 0
    y : int = 0

    ...

Vector2.UNIT_UP    = Vector2(0,1)
Vector2.UNIT_DOWN  = Vector2(0,-1)
Vector2.UNIT_LEFT  = Vector2(-1,0)
Vector2.UNIT_RIGHT = Vector2(1,0)
Vector2.ZERO       = Vector2(0,0)

请注意,我已经为ClassVar注释了下标,以指定它们将是Vector2实例,但是用引号将类型名称引为正向引用,因为类型没有评估注释时,该名称仍存在。在某些将来的Python版本(我认为是3.10还是4.0,取决于将来发行版的版本编号)中,不需要引号,或者您现在可以使用from __future__ import annotations来获得该行为。 / p>