正在定义的对象类型的类型提示

14

我遇到了这个错误:

NameError: name 'OrgUnit' is not defined
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时,我会得到正确的结果:

IBM_Worldwide
IBM_Worldwide->IBM_USA
IBM_Worldwide->IBM_Asia
IBM_Worldwide->IBM_Asia->IBM_China

我愿意接受想法和建议。这种事情最“pythonic”的做法是什么?

附注:这种“自引用类”范例/问题的名称是什么,我可以用它来查找其他建议?


1
请阅读这篇文章,并深入了解“鸭子类型” ;) - flaschbier
3
好的,如果他想使用类型提示,就让他用吧。 - Brian Cain
1个回答

29
你的问题是想使用类型提示,但又希望该类本身能够接受自身类型的参数。类型提示PEP(0484)解释了你可以使用类型的字符串版本名称作为前向引用。那里的示例是一个名为 Tree 的数据结构,听起来非常类似于这个 OrgUnit 。例如,以下内容是有效的:
class OrgUnit(object):

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

在Python 3.7中,您可以使用from __future__ import annotations激活annotations的延迟评估。这将自动将注释存储为字符串,而不是对其进行评估,因此您可以执行以下操作:
from __future__ import annotations

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

这将成为Python 4.0的默认设置。

这个确实可以工作,但是它不会对无效类型(例如字符串)引发任何问题,例如:failure_case = OrgUnit("Bad Unit", "a String")!在这种情况下不会出现错误。 - R. G. Abbott
在这种情况下没有错误?在执行期间?你为什么会期望出现错误? - Brian Cain
1
没有错误。Python故意不像Java :-) - miraculixx
@R. G. Abbott:还可以查看stackoverflow文档项目中Python语言类型提示部分的类成员和方法主题。 - martineau

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接