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
)。GasStation
的 fill_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()
依赖项作为属性注入,可以通过 self
或 module.user_repository
访问。
这个例子很简单,但 PyDIT 可以应用于各种项目配置、代码抽象和 SOLID 原则的场景。欢迎尝试并贡献代码!
代码仓库:Github
LinkedIn:Marcelo Almeida (MrM4rc)
PyPI:python-pydit
以上是Python 中输入的影响的详细内容。更多信息请关注PHP中文网其他相关文章!

热AI工具

Undresser.AI Undress
人工智能驱动的应用程序,用于创建逼真的裸体照片

AI Clothes Remover
用于从照片中去除衣服的在线人工智能工具。

Undress AI Tool
免费脱衣服图片

Clothoff.io
AI脱衣机

Video Face Swap
使用我们完全免费的人工智能换脸工具轻松在任何视频中换脸!

热门文章

热工具

记事本++7.3.1
好用且免费的代码编辑器

SublimeText3汉化版
中文版,非常好用

禅工作室 13.0.1
功能强大的PHP集成开发环境

Dreamweaver CS6
视觉化网页开发工具

SublimeText3 Mac版
神级代码编辑软件(SublimeText3)

Python适合数据科学、Web开发和自动化任务,而C 适用于系统编程、游戏开发和嵌入式系统。 Python以简洁和强大的生态系统着称,C 则以高性能和底层控制能力闻名。

2小时内可以学会Python的基本编程概念和技能。1.学习变量和数据类型,2.掌握控制流(条件语句和循环),3.理解函数的定义和使用,4.通过简单示例和代码片段快速上手Python编程。

Python在游戏和GUI开发中表现出色。1)游戏开发使用Pygame,提供绘图、音频等功能,适合创建2D游戏。2)GUI开发可选择Tkinter或PyQt,Tkinter简单易用,PyQt功能丰富,适合专业开发。

两小时内可以学到Python的基础知识。1.学习变量和数据类型,2.掌握控制结构如if语句和循环,3.了解函数的定义和使用。这些将帮助你开始编写简单的Python程序。

Python更易学且易用,C 则更强大但复杂。1.Python语法简洁,适合初学者,动态类型和自动内存管理使其易用,但可能导致运行时错误。2.C 提供低级控制和高级特性,适合高性能应用,但学习门槛高,需手动管理内存和类型安全。

要在有限的时间内最大化学习Python的效率,可以使用Python的datetime、time和schedule模块。1.datetime模块用于记录和规划学习时间。2.time模块帮助设置学习和休息时间。3.schedule模块自动化安排每周学习任务。

Python在web开发、数据科学、机器学习、自动化和脚本编写等领域有广泛应用。1)在web开发中,Django和Flask框架简化了开发过程。2)数据科学和机器学习领域,NumPy、Pandas、Scikit-learn和TensorFlow库提供了强大支持。3)自动化和脚本编写方面,Python适用于自动化测试和系统管理等任务。

Python在自动化、脚本编写和任务管理中表现出色。1)自动化:通过标准库如os、shutil实现文件备份。2)脚本编写:使用psutil库监控系统资源。3)任务管理:利用schedule库调度任务。Python的易用性和丰富库支持使其在这些领域中成为首选工具。
