两个 python 类 如何声明彼此和自身的引用?
How can two python classes declare references each other and itself?
这是一个非常基础的问题,实际上是两个问题合二为一。暴露我的 Python 绿色的希望非常简单的答案对于这两个问题可能是相同的。
下面的代码有两个问题:
- Class A
a:A=A()
创建了一个 NameError
因为 class A 在声明完成之前不知道 class A 存在。
- Class A
b:B=B()
创建了一个 NameError
因为 class A 不知道 class B 存在直到 class B 已经存在宣布。
#! /usr/bin/python3.10
class A:
a:A=A()
b:B=B()
class B:
a:A=A()
b:B=B()
我有类型错误,想使用 mypy。如果我在 class 声明之外创建变量作为属性或以其他方式隐藏所需的类型,则 mypy 将看不到类型声明并且无法解析我的程序以查找类型错误。
你可能会问我为什么要这个?递归数据结构有不定式的应用,但是...
- class 引用本身是一个简单的 link 列表的情况。 link 列表消除了跟踪索引的需要,同时允许简单的插入、删除和下一次迭代,但代价是应用程序可能永远不需要的缓慢索引。
- A 引用 class B 的情况 class B 引用 class A 是一个简单的容器,其中 class B(容器)包含一组实例class A(物品)知道它们所在的容器。
能否Python以 mypy 可以满足类型声明的方式做这些非常基本的事情?
我开始认为 'python way' 是为每个函数对每个参数进行类型检查。我越想越觉得解释型语言提出这样的要求是合乎逻辑的,但我还是希望我的代码尽可能保持井井有条和声明式。
我认为您的部分问题没有解决方案。您的声明:
class A:
a:A=A()
b:B=B()
表示 A().a 是 A 的另一个实例,A 又引用另一个 A,依此类推。这不一定是个问题,但如果它成为对象创建或实例化的一部分,将自动需要无限数量的对象!也许你可以这样做:
from typing import Optional
class A:
a: Optional["A"]
def __init__(self, other: Optional["A"] = None):
self.a = other
这将允许您有一个基本情况(self.a 是 None)和其他情况,其中 self.a 是 A 的另一个实例。
注意上面也用“A”来定义类型。这让你解决了类型提示问题,虽然我不知道它如何与 mypy 一起玩!您可以应用它,以便您的解决方案看起来像:
from typing import Optional
class A:
a: Optional["A"]
b: Optional["B"]
class B:
a: Optional["A"]
b: Optional["B"]
[根据评论中的讨论编辑答案。]
如果您想要使用 __init__
方法的递归 class 定义,那么正确的实现将取决于您的目标,但 可能是您想要的。但是,如果你真的需要静态 class 成员,你可以在声明两个 classes:
之后初始化它们
class A:
a: 'A'
b: 'B'
class B:
a: 'A'
b: 'B'
A.a = A()
A.b = B()
B.a = A()
B.b = B()
这是一个非常基础的问题,实际上是两个问题合二为一。暴露我的 Python 绿色的希望非常简单的答案对于这两个问题可能是相同的。
下面的代码有两个问题:
- Class A
a:A=A()
创建了一个NameError
因为 class A 在声明完成之前不知道 class A 存在。 - Class A
b:B=B()
创建了一个NameError
因为 class A 不知道 class B 存在直到 class B 已经存在宣布。
#! /usr/bin/python3.10
class A:
a:A=A()
b:B=B()
class B:
a:A=A()
b:B=B()
我有类型错误,想使用 mypy。如果我在 class 声明之外创建变量作为属性或以其他方式隐藏所需的类型,则 mypy 将看不到类型声明并且无法解析我的程序以查找类型错误。
你可能会问我为什么要这个?递归数据结构有不定式的应用,但是...
- class 引用本身是一个简单的 link 列表的情况。 link 列表消除了跟踪索引的需要,同时允许简单的插入、删除和下一次迭代,但代价是应用程序可能永远不需要的缓慢索引。
- A 引用 class B 的情况 class B 引用 class A 是一个简单的容器,其中 class B(容器)包含一组实例class A(物品)知道它们所在的容器。
能否Python以 mypy 可以满足类型声明的方式做这些非常基本的事情?
我开始认为 'python way' 是为每个函数对每个参数进行类型检查。我越想越觉得解释型语言提出这样的要求是合乎逻辑的,但我还是希望我的代码尽可能保持井井有条和声明式。
我认为您的部分问题没有解决方案。您的声明:
class A:
a:A=A()
b:B=B()
表示 A().a 是 A 的另一个实例,A 又引用另一个 A,依此类推。这不一定是个问题,但如果它成为对象创建或实例化的一部分,将自动需要无限数量的对象!也许你可以这样做:
from typing import Optional
class A:
a: Optional["A"]
def __init__(self, other: Optional["A"] = None):
self.a = other
这将允许您有一个基本情况(self.a 是 None)和其他情况,其中 self.a 是 A 的另一个实例。
注意上面也用“A”来定义类型。这让你解决了类型提示问题,虽然我不知道它如何与 mypy 一起玩!您可以应用它,以便您的解决方案看起来像:
from typing import Optional
class A:
a: Optional["A"]
b: Optional["B"]
class B:
a: Optional["A"]
b: Optional["B"]
[根据评论中的讨论编辑答案。]
如果您想要使用 __init__
方法的递归 class 定义,那么正确的实现将取决于您的目标,但
class A:
a: 'A'
b: 'B'
class B:
a: 'A'
b: 'B'
A.a = A()
A.b = B()
B.a = A()
B.b = B()