Python:如何在其内部引用一个类?

che*_*eng 17 python class self-reference

尝试在其内部引用一个类。例如

class Test:
    FOO_DICT = {1 : Test.bar}  # NameError: name 'Test' is not defined

    @staticmethod
    def bar():
        pass
Run Code Online (Sandbox Code Playgroud)

这种用法有意义吗?还有更好的选择吗?谢谢!

Vic*_*hor 13

您不需要引用自身内部的类,使用 bar 而不是 Test.bar 就可以正常工作。

class Test:
    @staticmethod
    def bar():
        pass

    FOO_DICT = {1: bar}


# You can access this outside of the class by simply using Test.FOO_DICT
print(Test.FOO_DICT)
Run Code Online (Sandbox Code Playgroud)

然而,在某些情况下,您确实需要使用类本身。例如

class Test:
    @staticmethod
    def bar():
        pass

    def test_with_other_of_same_instance(self, other: Test):
        print(other.FOO_DICT)

    FOO_DICT = {1: bar}
Run Code Online (Sandbox Code Playgroud)

在这种情况下,

  • 我想定义一个接受同一 Test 类的对象的方法。
  • 我想使用 python 的类型提示来指示预期的参数是 Test 的实例。这使我能够获得编辑器支持,并且如果我传递了错误数据类型的参数,pylance 和 mypy 等工具可以通知我可能出现的错误。

在撰写本文时,我将收到一个 NameError:名称“Test”未定义。

这是因为默认情况下我不能在其内部使用类(Python 的更高版本可能会更改其默认行为,因此到那时我们将不需要下面的解决方案)。

但是,如果您使用3.7+的 Python 版本,并且无法在其内部引用类,则PEP 563 - 延迟评估注释提供了简单的解决方案。是通过在文件的第一行添加一小行代码来实现的

from __future__ import annotations
# other imports or code come afterwards


class Test:
    @staticmethod
    def bar():
        pass

    def test_with_other_of_same_instance(self, other: Test):
        print(other.FOO_DICT)

    FOO_DICT = {1: bar}
Run Code Online (Sandbox Code Playgroud)

因此,您只需在文件开头包含该行即可在 python 中使用其自身的类。

通常,如果您使用 pylance 或任何类似工具,您会收到警告或错误显示,表明您导入了某些内容但没有使用它。但在注释的情况下则不然。您不必担心编辑的任何警告。

请注意,这必须出现在文件的开头,否则您会收到 SyntaxError 并且 3.7 之前的版本将不支持此操作


Har*_*uin 5

如果您希望字典位于类中:首先定义函数并删除 Test:

class Test:
    @staticmethod
    def bar():
         pass

    FOO_DICT = {1: bar}
Run Code Online (Sandbox Code Playgroud)