首頁 > 後端開發 > Python教學 > Python 中輸入的影響

Python 中輸入的影響

Susan Sarandon
發布: 2025-01-16 22:13:14
原創
677 人瀏覽過

O impacto da tipagem no python

Python 3.5 版本引入了“類型提示”,使程式碼更易讀,方便開發者理解彼此的程式碼。

為什麼類型提示至關重要?

在 Java、C 等強型別語言中,依賴反轉 (DI - Dependency Inversion) 是一項重要的技術,但在弱型別語言中難以實現。

依賴反轉的核心思想是:類別不應該依賴具體的實現,而應該依賴抽象。因為抽象(介面或抽象類別)是相對穩定的契約。

不良範例:

class GasStation:
    def fill_tank(car, amount):
        car.fill(amount)
登入後複製

此例中,加油站只能為汽車加油。更糟的是,由於函數 fill_tank 沒有定義類型,任何值都可能被傳入,錯誤只能在運行時才能發現。

良好範例:

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)
登入後複製

此例中,先定義抽象類別 Vehicle (使用 typing.Protocol)。 GasStationfill_tank 函數不再依賴具體的汽車類,而是依賴 Vehicle 接口,從而變得更通用,可以為任何實現了 fill 方法的車輛加油。

什麼是 PyDIT?

我利用 Python 的類型提示系統,創建了一個簡化依賴反轉使用的函式庫,名為 PyDIT (Python Dependency Injection with Types)。

假設需要一個用於儲存使用者資料的資料庫接口,無論使用 PostgreSQL、MySQL、OracleDB、記憶體資料庫或 NoSQL 資料庫,都需要實作資料庫連接類,並提供讀取、寫入、刪記錄的功能。

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")
登入後複製

為了確保程式碼與資料庫技術無關,定義一個所有資料庫類別都必須遵循的介面:

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
登入後複製

接下來,初始化相依性以便注入:

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")
登入後複製

最後,將相依性注入到建立使用者的模組中:

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()
登入後複製

依賴項作為屬性注入,可以透過 selfmodule.user_repository 存取。

這個範例很簡單,但 PyDIT 可以應用於各種專案配置、程式碼抽象化和 SOLID 原則的場景。歡迎嘗試並貢獻程式碼!

代碼倉庫:Github
LinkedIn:Marcelo Almeida (MrM4rc)
PyPI:python-pydit

以上是Python 中輸入的影響的詳細內容。更多資訊請關注PHP中文網其他相關文章!

本網站聲明
本文內容由網友自願投稿,版權歸原作者所有。本站不承擔相應的法律責任。如發現涉嫌抄襲或侵權的內容,請聯絡admin@php.cn
作者最新文章
熱門教學
更多>
最新下載
更多>
網站特效
網站源碼
網站素材
前端模板