如何在Python类定义中创建一个指向自身类型的属性?
例如:
class People(object):
name = “”
friend = People()
由于 friend 还在类 People 的定义中,这里是不能引用 People 类的,请问这种情况代码该如何写?
相似的还有:
class A:
b = B()
class B:
a = A()
B 类可以引用 A 类,A 里面是不能引用 B 的,这种情况代码如何写?
如何在Python类定义中创建一个指向自身类型的属性?
标准库里一般有两种做法,一种是像 enum 这样的用 metaclass 黑魔法,另一种就是先创建类,然后再添加属性,比如
class A: pass
class B: pass
A.b = B()
B.a = A()
在Python类定义中创建指向自身类型的属性,可以通过使用类型注解配合typing模块的'TypeVar'和'ClassVar'来实现,或者利用Python 3.7+的from __future__ import annotations特性。最直接和现代的方法是使用字符串字面量注解。
下面是一个清晰的示例:
from typing import ClassVar, Optional
class TreeNode:
# 使用字符串字面量注解声明一个类变量,其类型是类自身
parent: ClassVar[Optional['TreeNode']] = None
def __init__(self, value: int):
self.value = value
self.children: list['TreeNode'] = [] # 实例变量也可以这样注解
def add_child(self, child: 'TreeNode') -> None:
self.children.append(child)
# 假设我们设置父节点(这里仅为示例逻辑)
# child.parent = self
# 使用示例
if __name__ == "__main__":
root = TreeNode(1)
child1 = TreeNode(2)
root.add_child(child1)
print(f"Root's first child value: {root.children[0].value}")
关键点解释:
ClassVar: 用于注解类变量(属于类本身,而不是实例)。这里parent被定义为可选的'TreeNode'类型,并初始化为None。- 字符串字面量
'TreeNode': 在类定义内部,类名尚未完全定义。使用引号将其包裹(前向引用)可以解决这个问题。这是Python 3.7+的标准做法,也适用于实例方法参数和返回值的注解(如add_child方法)。 Optional: 表示该属性可以是TreeNode类型或None。
如果你的Python版本是3.7+,并且脚本开头有from __future__ import annotations,那么可以省略字符串引号,但为了代码的清晰和兼容性,通常建议保留字符串形式。
对于更复杂的自引用,比如在泛型中,可能会用到TypeVar,但针对“类自身类型”这个常见需求,上面的方法就足够了。
总结:用字符串字面量做前向引用。
应该用 new 新建对象吧
其实出现这个需求是我在使用 django RESTframework 做序列化时遇到的。
我在 django 中定义了一个类型的 model:
class Channel(models.Model):
“”"
分类
“”"
name = models.CharField(verbose_name=“分类名称”, max_length=40)
display_name = models.CharField(verbose_name=“显示名称”, max_length=40)
parent = models.ForeignKey(“Channel”, null=True, blank=True, related_name=“sub_channels”, on_delete=models.SET_NULL)
Channel 对象的 parent 属性可以指向自己类型的对象。
做序列化时,就要定义
class ChannelSerializer(serializers.ModelSerializer):
parent = ChannelSerializer(read_only=True)
class Meta:
model = Channel
fields = 'all’
这样的代码,这就不符合 Python 的语法了。
使用你给出的解决办法,结果不对,没有达到享耀的效果。
classmethod 会传入这个 class
请问 classmethod 该如何使用?查了些资料,都没提到解决这种情况的。
这和我问的问题有关系吗?
self.class
sorry 刚才没看仔细,其实一楼是符合你最初的描述的,不过不符合你的需求。
你的要求是自引用序列化,可以看下这个,对于实在需要自定义程度很大的字段其实可以覆写他的 create valid 方法。
http://www.google.com/url?q=https://stackoverflow.com/questions/13376894/django-rest-framework-nested-self-referential-objects&sa=U&ved=2ahUKEwihxJmZ5_HcAhXov1QKHT0ECmcQFjAAegQIBxAB&usg=AOvVaw06lQugVRb1STGxI0PRr3Lz
self 是在类的实例中使用的,引用类的实例,也就是对象本身。现在需要的是类定义时,引用其自身。或者两个类相互引用时,前一个类如何引用后一个类的类型。

