python中的自引用类?

ams*_*age 3 python class

在Python中,您是否可以拥有成员的类,这些成员本身就是指向同一类类型成员的指针?例如,在C中,您可能在二叉树中具有以下类的节点:

struct node {
    int data;
    struct node* left;
    struct node* right;
} 
Run Code Online (Sandbox Code Playgroud)

你会如何在python中等效地创建它?

小智 16

我认为这可能会有所帮助

from typing_extensions import Self


class Node:
    """Binary tree node."""

    def __init__(self, left: Self, right: Self):
        self.left = left
        self.right = right
Run Code Online (Sandbox Code Playgroud)

Typing_extensions 提供了一个 Self 类来引用类本身,我认为这是最优雅的自我引用方式(PEP 673)。


正如其他人提到的,您还可以使用字符串文字。但当你有多种类型提示时,就会出现问题。

# python 3.10
var: str | int
Run Code Online (Sandbox Code Playgroud)

然后你写一些类似的东西

class Node:
    def __init__(self, var: 'Node' | SomeClass):
        self.var = var
Run Code Online (Sandbox Code Playgroud)

它将引发 TypeError: unsupported operand type(s) for |: 'str' and 'type'。


Joh*_*hin 8

在Python中模拟C结构(使用str而不是int作为数据类型):

"宣言":

class Node(object):
    data = None # str
    left = None # Node object or None
    right = None # Node object or None
Run Code Online (Sandbox Code Playgroud)

用法:

root = Node()
root.data = "foo"

b = Node()
b.data = "bar"
root.left = b

z = Node()
z.data = "zot"
root.right = z
Run Code Online (Sandbox Code Playgroud)

  • 你在这里宣布班级成员,而不是实例成员,不是吗? (4认同)
  • @Russell Borogove:你从未意识到什么? (2认同)

Ign*_*ams 7

Python是一种动态语言.属性可以在任何时候(几乎)与任何类型绑定.因此,Python中不存在您描述的问题.

  • 啊?这没有回答OP的问题“”“你如何在Python中等效地创建这个?”“” (3认同)
  • @John:多年来对 IRC 的支持告诉你,人们并不总是问他们想要回答的问题。 (2认同)

use*_*695 6

虽然正如其他答案所指出的那样,由于动态类型,这不是问题,但实际上,对于 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)
Run Code Online (Sandbox Code Playgroud)

结果是:

   def do_something_with_other_instance_of_a(self, other: A):
   NameError: name 'A' is not defined
Run Code Online (Sandbox Code Playgroud)

更多关于这里问题的性质:https : //www.python.org/dev/peps/pep-0484/#the-problem-of-forward-declarations

您可以使用字符串文字来避免前向引用

在此处输入图片说明

在这种情况下,另一种方法是不使用 python3 样式的类型注释,

如果您必须使代码与早期版本的 Python 兼容,这是唯一的方法。

相反,为了在我的 IDE (PyCharm) 中获得自动完成功能,您可以使用这样的文档字符串:

使用 python 文档字符串而不是类型提示来避免类自引用

更新: 或者,您可以注释使用“type:”注释,而不是使用文档字符串。这也将确保 mypy 静态类型检查将起作用(mypy 似乎并不关心文档字符串):

在此处输入图片说明