Python中的自引用类?
在Python中,你能否创建一个类,其中的成员本身是指向同一个类的其他成员的指针?比如在C语言中,你可能会有这样一个表示二叉树节点的类:
struct node {
int data;
struct node* left;
struct node* right;
}
那么在Python中,你该如何等效地创建这个呢?
9 个回答
16
我觉得这可能会对你有帮助。
from typing_extensions import Self
class Node:
"""Binary tree node."""
def __init__(self, left: Self, right: Self):
self.left = left
self.right = right
typing_extensions 提供了一个 Self 类,可以用来引用类本身,我觉得这是自我引用最优雅的方式(PEP 673)。
正如其他人提到的,你也可以使用字符串字面量(就是直接写字符串)。但是当你有多个类型提示的时候,就会出现问题。
# python 3.10
var: str | int
然后你写一些像这样的代码:
class Node:
def __init__(self, var: 'Node' | SomeClass):
self.var = var
这会引发一个错误,提示类型错误:不支持的操作数类型('str' 和 'type')。
18
虽然其他回答提到这不是因为动态类型的问题,但实际上在Python3中,这在类型注解方面是个很真实的问题。而且这样写是行不通的(注意方法参数的类型注解):
class A:
def do_something_with_other_instance_of_a(self, other: A):
print(type(other).__name__)
instance = A()
other_instance = A()
instance.do_something_with_other_instance_of_a(other_instance)
结果是:
def do_something_with_other_instance_of_a(self, other: A):
NameError: name 'A' is not defined
关于这个问题的更多信息可以在这里找到: https://www.python.org/dev/peps/pep-0484/#the-problem-of-forward-declarations
你可以使用字符串字面量来避免前向引用
另一种方法是在这种情况下不使用Python3风格的类型注解,
如果你需要保持代码与早期版本的Python兼容,这也是唯一的方法。
为了在我的IDE(PyCharm)中获得自动补全,你可以使用这样的文档字符串:
更新: 另外,除了使用文档字符串,你还可以在注释中使用"type: "注解。这也能确保mypy静态类型检查能够正常工作(mypy似乎不关心文档字符串):
5
Python是一种动态语言。这意味着你可以在几乎任何时候给对象添加属性,而且可以使用任何类型的值。所以,你提到的问题在Python中是不存在的。