Get started with Python type hints




class User:
    def __init__(self, name: str, address: "Address"):
        self.name = name
        self.address = address
        # ^ because let's say for some reason we must have
        # an address for each user

class Address:
    def __init__(self, owner: User, address_line: str):
        self.owner = owner
        self.address_line = address_line

This approach is useful if you have objects with interdependencies, as in the above example. There is probably a more elegant way to untangle it, but at least you can provide ahead-of-time hints in the same namespace simply by providing the name of the object.

However, a better way to do this is to use a feature called deferred evaluation of annotations. You can use a special import to change the way annotations are resolved at the module level:


from __future__ import annotations

class User:
    def __init__(self, name: str, address: Address):
        self.name = name
        self.address = address
        # ^ because let's say for some reason we must have
        # an address for each user

class Address:
    def __init__(self, owner: User, address_line: str):
        self.owner = owner
        self.address_line = address_line

When you add from __future__ import annotations at the top of a module, annotations are now resolved lazily for that module—just as if they were string hints, but the actual object is referred to instead of just its name. This allows linters to resolve things far more powerfully and completely, which is why it’s the recommended solution for this problem. You can still use string hints where they’re expected, but they should be phased out.



Source link