R. G. Abbott R. G. Abbott - 3 months ago 9
Python Question

Python Type Hinting for objects of type that's being defined

I get the error:

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)


I am sure this is a known paradigm, as it seems like a pretty common hierarchical class usage issue (a self referencing class). I know I could change the type of
its_parent_org_unit
to be
object
and it works, but this seems like the wrong thing to do, primarily since it scuppers my ability to check types in my calls. With
its_parent_org_unit
changed to be a type
object
I get the correct results:

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


I am open to thoughts and suggestions. What is the most "pythonic" way to do this sort of thing?

PS: What is the name for this sort of "self referencing class" paradigm/problem, which I could use to look up other suggestions?

Answer

Your problem is that you want to use type hints but you want this class itself to be able to take arguments of its own type.

The type hints PEP (0484) explains that you can use the string version of the type's name as a forward reference. The example there is of a Tree data structure which sounds remarkably similar to this OrgUnit one.

For example, this works:

class OrgUnit(object):

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