在Python中在类内创建类的静态实例

27 投票
4 回答
4234 浏览
提问于 2025-04-15 21:02

抱歉,如果我用错了术语——我想不出这个特定的说法该叫什么。

我一直在尝试创建一个Python 3的类,这个类可以在内部静态声明它自己的实例——有点像枚举(enum)的工作方式。下面是我写的代码的简化版本:

class Test:
    A = Test("A")
    B = Test("B")

    def __init__(self, value):
        self.value = value

    def __str__(self):
       return "Test: " + self.value

print(str(Test.A))
print(str(Test.B))

在写这段代码时,我在第2行(A = Test("A"))遇到了一个异常。我猜第3行如果能执行到的话也会出错。用__class__代替Test也会出现同样的错误。

  File "<stdin>", line 1, in <module>
  File "<stdin>", line 2, in Test
NameError: name 'Test' is not defined

在Python中,有没有办法在静态上下文中引用当前类?我可以把这些变量声明在类外面或者在一个单独的类里,但为了清晰起见,如果可以的话,我更希望不这样做。

为了更好地展示我想做的事情,这里是同样的例子在Java中的写法:

public class Test {
    private static final Test A = new Test("A");
    private static final Test B = new Test("B");

    private final String value;

    public Test(String value) {
        this.value = value;
    }

    public String toString() {
        return "Test: " + value;
    }

    public static void main(String[] args) {
        System.out.println(A);
        System.out.println(B);
    }
}

这个在Java中按预期工作:它打印出:

Test: A
Test: B

我该如何在Python中做到这一点呢?

4 个回答

4

在Python中,class块不仅仅是一个声明,它在运行时会被执行来构建这个类。每个在类里面的def都会创建一个函数,并把这个函数的名字绑定到类的命名空间里。因此,你不能直接在类块里面写A = MyClass(),因为在类块结束之前,MyClass()还没有完全定义好。下面是正确的做法:

class Test:
    def __init__(self, value):
        self.value = value

    def __str__(self):
       return "Test: " + self.value

Test.A = Test("A")
Test.B = Test("B")
4

虽然Aaron的回答是推荐的做法,但你也可以使用元类:

>>> class TestMeta(type):
...  def __init__(cls, name, bases, dct):
...   cls.A = cls()
...   cls.B = cls()
... 
>>> class Test:
...   __metaclass__ = TestMeta
... 
>>> Test
<class __main__.Test at 0x7f70f8799770>
>>> Test.A
<__main__.Test object at 0x7f70f86f2e10>
>>> Test.B
<__main__.Test object at 0x7f70f86f2e90>
>>> 
22

在你定义好这个类之后,只需要加上这两行代码:

Test.A = Test("A")
Test.B = Test("B")

在Python中,类也是一种对象,就像其他对象一样,你可以随时添加新的变量。不过,你不能在类内部添加这些变量,因为那时候它们还没有被定义(这些变量只有在整个类的代码被正确解析后,才会被加入到符号表中)。

撰写回答