关于python:正在定义的类型的对象的类型提示

Type Hinting for objects of type that's being defined

我得到错误:

1
NameError: name 'OrgUnit' is not defined
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
class OrgUnit(object):

    def __init__(self,
                 an_org_name: str,
                 its_parent_org_unit: OrgUnit= None
                 ):
        self.org_unit_name = an_org_name
        self.parent_org_unit = its_parent_org_unit

    def __str__(self):
        if self.parent_org_unit:
            parent_org_unit_name = self.parent_org_unit.__str__()
            return parent_org_unit_name +"->" + self.org_unit_name
        else:
            return self.org_unit_name


if __name__ == '__main__':
    ibm_worldwide = OrgUnit("IBM_Worldwide")
    ibm_usa = OrgUnit("IBM_USA", ibm_worldwide)
    ibm_asia = OrgUnit("IBM_Asia", ibm_worldwide)
    ibm_china = OrgUnit("IBM_China", ibm_asia)
    print(ibm_worldwide)
    print(ibm_usa)
    print(ibm_asia)
    print(ibm_china)

我确信这是一个已知的范例,因为它看起来像一个非常常见的层次类使用问题(一个自引用类)。我知道我可以将its_parent_org_unit的类型改为object的类型,而且它可以工作,但这似乎是错误的做法,主要是因为它破坏了我在呼叫中检查类型的能力。当its_parent_org_unit改为object型时,我得到了正确的结果:

1
2
3
4
IBM_Worldwide
IBM_Worldwide->IBM_USA
IBM_Worldwide->IBM_Asia
IBM_Worldwide->IBM_Asia->IBM_China

我乐于接受各种想法和建议。做这种事最"Python式"的方法是什么?

PS:这种"自引用类"范式/问题的名称是什么,我可以用它来查找其他建议?


您的问题是,您希望使用类型提示,但您希望此类本身能够接受其自身类型的参数。

类型提示PEP(0484)解释了可以使用类型名称的字符串版本作为前向引用。这里有一个Tree数据结构的例子,听起来与这个OrgUnit数据结构非常相似。

例如,这是可行的:

1
2
3
4
5
6
class OrgUnit(object):

    def __init__(self,
                 an_org_name: str,
                 its_parent_org_unit: 'OrgUnit' = None
                 ):

在Python3.7中,您将能够使用from __future__ import annotations激活注释的延迟评估。这将自动将注释存储为字符串,而不是对其进行计算,因此可以这样做

1
2
3
4
5
6
7
8
from __future__ import annotations

class OrgUnit(object):
    def __init__(self,
                 an_org_name: str,
                 its_parent_org_unit: OrgUnit= None
                 ):
        ...

这被安排成Python4.0中的默认值。