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?
Introduction to Type Hints As the code base gets larger, type hints can help to debug and prevent some dumb mistakes. If you're using an IDE like PyCharm, you'll get a warning message whenever you've used the wrong data type, provided you're using type hints.
Type hints improve IDEs and linters. They make it much easier to statically reason about your code. Type hints help you build and maintain a cleaner architecture. The act of writing type hints forces you to think about the types in your program.
Introduction to Python type hints It means that you need to declare types of variables, parameters, and return values of a function upfront. The predefined types allow the compilers to check the code before compiling and running the program.
Python will always remain a dynamically typed language. However, PEP 484 introduced type hints, which make it possible to also do static type checking of Python code. Unlike how types work in most other statically typed languages, type hints by themselves don't cause Python to enforce types.
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
):
In Python 3.7, you will be able to activate postponed evaluation of annotations with from __future__ import annotations
. This will automatically store annotations as strings instead of evaluating them, so you can do
from __future__ import annotations
class OrgUnit(object):
def __init__(self,
an_org_name: str,
its_parent_org_unit: OrgUnit= None
):
...
This is scheduled to become the default in Python 4.0.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With