class Person:
def __init__(self, identify: str, deal with: "Handle"):
self.identify = identify
self.deal with = deal with
# ^ as a result of as an example for some purpose we will need to have
# an deal with for every consumer
class Handle:
def __init__(self, proprietor: Person, address_line: str):
self.proprietor = proprietor
self.address_line = address_line
This strategy is beneficial when you have objects with interdependencies, as within the above instance. There may be most likely a extra elegant strategy to untangle it, however no less than you’ll be able to present ahead-of-time hints in the identical namespace just by offering the identify of the item.
Nonetheless, a greater method to do that is to make use of a characteristic referred to as deferred analysis of annotations. You should utilize a particular import to vary the best way annotations are resolved on the module degree:
from __future__ import annotations
class Person:
def __init__(self, identify: str, deal with: Handle):
self.identify = identify
self.deal with = deal with
# ^ as a result of as an example for some purpose we will need to have
# an deal with for every consumer
class Handle:
def __init__(self, proprietor: Person, address_line: str):
self.proprietor = proprietor
self.address_line = address_line
Whenever you add from __future__ import annotations
on the high of a module, annotations are actually resolved lazily for that module—simply as in the event that they had been string hints, however the precise object is referred to as a substitute of simply its identify. This permits linters to resolve issues way more powerfully and utterly, which is why it’s the advisable answer for this drawback. You’ll be able to nonetheless use string hints the place they’re anticipated, however they need to be phased out.