> 백엔드 개발 > 파이썬 튜토리얼 > Python에서 타이핑이 미치는 영향

Python에서 타이핑이 미치는 영향

Susan Sarandon
풀어 주다: 2025-01-16 22:13:14
원래의
580명이 탐색했습니다.

O impacto da tipagem no python

Python 버전 3.5에는 코드를 더 읽기 쉽게 만들고 개발자가 서로의 코드를 쉽게 이해할 수 있도록 '유형 힌트'가 도입되었습니다.

유형 힌트가 왜 중요한가요?

Java, C 등 강형 언어에서는 종속성 역전(DI - dependency Inversion)이 중요한 기술이지만 약형 언어에서는 구현하기 어렵습니다.

종속성 역전의 핵심 아이디어는 클래스가 특정 구현에 의존하지 않고 추상화에 의존해야 한다는 것입니다. 추상화(인터페이스 또는 추상 클래스)는 상대적으로 안정적인 계약이기 때문입니다.

나쁜 예:

<code class="language-python">class GasStation:
    def fill_tank(car, amount):
        car.fill(amount)</code>
로그인 후 복사

이 예에서 주유소에서는 자동차에 주유만 할 수 있습니다. 설상가상으로 fill_tank 함수에는 정의된 유형이 없으므로 모든 값이 전달될 수 있으며 오류는 런타임에만 발견됩니다.

좋은 예:

<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>
로그인 후 복사

이 예에서는 먼저 추상 클래스 Vehicle를 정의합니다(typing.Protocol 사용). GasStationfill_tank 기능은 더 이상 특정 자동차 클래스에 의존하지 않고 Vehicle 인터페이스에 의존하므로 더욱 일반화되고 fill 메서드를 구현하는 모든 차량에 연료를 공급할 수 있습니다.

PyDIT란 무엇인가요?

Python의 유형 힌트 시스템을 활용하여 PyDIT(Python 종속성 주입 with 유형)라는 종속성 반전 사용을 단순화하는 라이브러리를 만들었습니다.

사용자 데이터를 저장하기 위한 데이터베이스 인터페이스가 필요하다고 가정해 보겠습니다. PostgreSQL, MySQL, OracleDB, 인메모리 데이터베이스 또는 NoSQL 데이터베이스를 사용하든 데이터베이스 연결 클래스를 구현하고 레코드 읽기, 쓰기 및 삭제 기능을 제공해야 합니다. .

<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>
로그인 후 복사

코드가 데이터베이스 기술과 아무 관련이 없는지 확인하려면 모든 데이터베이스 클래스가 따라야 하는 인터페이스를 정의하세요.

<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>
로그인 후 복사

다음으로 주입을 위한 종속성을 초기화합니다.

<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>
로그인 후 복사

마지막으로 사용자를 생성하는 모듈에 종속성을 삽입합니다.

<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>
로그인 후 복사

종속성은 속성으로 주입되며 self 또는 module.user_repository 을 통해 액세스할 수 있습니다.

이 예는 간단하지만 PyDIT는 다양한 프로젝트 구성, 코드 추상화 및 SOLID 원칙 시나리오에 적용될 수 있습니다. 코드를 시도하고 기여해 주셔서 감사합니다!

코드 저장소: Github
LinkedIn: Marcelo Almeida(MrM4rc)
PyPI: python-pydit

위 내용은 Python에서 타이핑이 미치는 영향의 상세 내용입니다. 자세한 내용은 PHP 중국어 웹사이트의 기타 관련 기사를 참조하세요!

원천:php.cn
본 웹사이트의 성명
본 글의 내용은 네티즌들의 자발적인 기여로 작성되었으며, 저작권은 원저작자에게 있습니다. 본 사이트는 이에 상응하는 법적 책임을 지지 않습니다. 표절이나 침해가 의심되는 콘텐츠를 발견한 경우 admin@php.cn으로 문의하세요.
저자별 최신 기사
인기 튜토리얼
더>
최신 다운로드
더>
웹 효과
웹사이트 소스 코드
웹사이트 자료
프론트엔드 템플릿