Home >Backend Development >Python Tutorial >The impact of typing in Python

The impact of typing in Python

Susan Sarandon
Susan SarandonOriginal
2025-01-16 22:13:14582browse

O impacto da tipagem no python

Python version 3.5 introduces "type hints" to make the code more readable and facilitate developers to understand each other's code.

Why are type hints important?

In strongly typed languages ​​such as Java and C, dependency inversion (DI - Dependency Inversion) is an important technology, but it is difficult to implement in weakly typed languages.

The core idea of ​​dependency inversion is: classes should not rely on specific implementations, but on abstractions. Because abstractions (interfaces or abstract classes) are relatively stable contracts.

Bad example:

<code class="language-python">class GasStation:
    def fill_tank(car, amount):
        car.fill(amount)</code>

In this example, the gas station can only refuel cars. To make matters worse, since function fill_tank has no defined type, any value may be passed in and the error will only be discovered at runtime.

Good example:

<code class="language-python">from typing import Protocol

class Vehicle(Protocol):
    def fill(amount: int) -> None:
        ...
class GasStation:
    def fill_tank(vehicle: Vehicle, amount: int) -> None:
        vehicle.fill(amount)</code>

In this example, first define the abstract class Vehicle (using typing.Protocol). The GasStation function of fill_tank no longer relies on a specific car class, but on the Vehicle interface, thus becoming more general and can refuel any vehicle that implements the fill method.

What is PyDIT?

I took advantage of Python's type hinting system and created a library that simplifies the use of dependency inversion, called PyDIT (Python Dependency Injection with Types).

Suppose you need a database interface for storing user data. Whether you use PostgreSQL, MySQL, OracleDB, in-memory database or NoSQL database, you need to implement a database connection class and provide the functions of reading, writing and deleting records.

<code class="language-python">from time import sleep
from typing import TypedDict
from typing_extensions import override
from uuid import UUID
from src.configs.di import pydit
from src.adapters.repositories.interfaces.user import UserRepository
from src.constants.injection import MEMORY_REPOSITORY_CONFIG_TOKEN
from src.domain.user.models.user import UserModel


class ConfigType(TypedDict):
    delay: int


class MemoryUserRepository(UserRepository):

    __users: dict[UUID, UserModel] = {}

    def __init__(self):
        self.__delay = self.config.get("delay", 0.2)

    @pydit.inject(token=MEMORY_REPOSITORY_CONFIG_TOKEN)
    def config(self) -> ConfigType:  # TODO: supress return type error
        pass

    @override
    def get_by_id(self, *, id_: UUID) -> UserModel:
        sleep(self.__delay)

        user = self.__users.get(id_)

        if user is None:
            raise ValueError("User not found")

        return user

    @override
    def save(self, *, data: UserModel) -> None:
        sleep(self.__delay)
        self._check_pk_conflict(pk=data.id)

        self.__users[data.id] = data

    @override
    def list_(self) -> list[UserModel]:
        return list(self.__users.values())

    def _check_pk_conflict(self, *, pk: UUID) -> None:
        if pk not in self.__users:
            return

        raise ValueError("Primary key conflicts: DB alrady has a user with this ID")</code>

In order to ensure that the code has nothing to do with database technology, define an interface that all database classes must follow:

<code class="language-python">from abc import abstractmethod
from typing import Protocol
from uuid import UUID
from src.domain.user.models.user import UserModel


class UserRepository(Protocol):
    @abstractmethod
    def get_by_id(self, *, id_: UUID) -> UserModel:
        pass

    @abstractmethod
    def save(self, *, data: UserModel) -> None:
        pass

    @abstractmethod
    def list_(self) -> list[UserModel]:
        pass</code>

Next, initialize the dependencies for injection:

<code class="language-python">from src.adapters.repositories.in_memory.user import MemoryUserRepository
from src.constants.injection import MEMORY_REPOSITORY_CONFIG_TOKEN
from .di import pydit
from .get_db_config import get_db_config


def setup_dependencies():
    pydit.add_dependency(get_db_config, token=MEMORY_REPOSITORY_CONFIG_TOKEN)
    pydit.add_dependency(MemoryUserRepository, "UserRepository")</code>

Finally, inject the dependencies into the module that creates the user:

<code class="language-python">from typing import cast
from src.adapters.repositories.interfaces.user import UserRepository
from src.configs.di import pydit
from src.domain.user.models.create_user import CreateUserModel
from src.domain.user.models.user import UserModel
from src.domain.user.services.create import CreateUserService
from src.domain.user.services.list import ListUsersService


class UserModule:
    @pydit.inject()
    def user_repository(self) -> UserRepository:
        return cast(UserRepository, None)

    def create(self, data: CreateUserModel) -> None:
        CreateUserService(self.user_repository).execute(data)

    def list_(self) -> list[UserModel]:
        return ListUsersService().execute()</code>

Dependencies are injected as properties and can be accessed via self or module.user_repository .

This example is simple, but PyDIT can be applied to a variety of project configurations, code abstractions, and SOLID principle scenarios. Welcome to try and contribute code!

Code repository: Github
LinkedIn: Marcelo Almeida (MrM4rc)
PyPI: python-pydit

The above is the detailed content of The impact of typing in Python. For more information, please follow other related articles on the PHP Chinese website!

Statement:
The content of this article is voluntarily contributed by netizens, and the copyright belongs to the original author. This site does not assume corresponding legal responsibility. If you find any content suspected of plagiarism or infringement, please contact admin@php.cn