• DI Dependency Injection


    DI

    https://www.professionalqa.com/dependency-injection

    What is Dependency Injection?

    A software design pattern that implements inversion of control for resolving dependencies is known as Dependency Injection. In dependency injection a ‘dependency’ is an object that can be used (service) and ‘injection’ is the passing of a dependency to a dependent object or a client that would use it. Dependency Injection is a subset of Inversion of Control (IOC) that supports the dependency inversion principle and is a way of injecting properties to an object. Additionally, it explains how to inject the concrete implementation into an object that is using abstraction. The main idea of Dependency Injection is to reduce the coupling between objects and to move the binding of abstraction and concrete implementation out of the dependent object. Dependency injection is how one object gets information about the other dependent object, which is abstracted. Moreover, dependency injection provides objects what they require and ensure that this process is hassle free.

    WHY?

    http://www.jeremybytes.com/Downloads/DependencyInjection.pdf

    injector -- Python dependency injection framework, inspired by Guice

    https://github.com/alecthomas/injector

    While dependency injection is easy to do in Python due to its support for keyword arguments, the ease with which objects can be mocked and its dynamic nature, a framework for assisting in this process can remove a lot of boiler-plate from larger applications. That's where Injector can help. It automatically and transitively provides dependencies for you. As an added benefit, Injector encourages nicely compartmentalised code through the use of :ref:modules <module>.

    If you're not sure what dependency injection is or you'd like to learn more about it see:

    >>> from injector import Injector, inject
    >>> class Inner:
    ...     def __init__(self):
    ...         self.forty_two = 42
    ...
    >>> class Outer:
    ...     @inject
    ...     def __init__(self, inner: Inner):
    ...         self.inner = inner
    ...
    >>> injector = Injector()
    >>> outer = injector.get(Outer)
    >>> outer.inner.forty_two
    42

    dependency-injector

    https://python-dependency-injector.ets-labs.org/index.html

    Dependency Injector is a dependency injection framework for Python.

    It helps implementing the dependency injection principle.

    Key features of the Dependency Injector:

    • Providers. Provides Factory, Singleton, Callable, Coroutine, Object, List, Dict, Configuration, Resource, Dependency, and Selector providers that help assemble your objects. See Providers.

    • Overriding. Can override any provider by another provider on the fly. This helps in testing and configuring dev/stage environment to replace API clients with stubs etc. See Provider overriding.

    • Configuration. Reads configuration from yaml, ini, and json files, pydantic settings, environment variables, and dictionaries. See Configuration provider.

    • Resources. Helps with initialization and configuring of logging, event loop, thread or process pool, etc. Can be used for per-function execution scope in tandem with wiring. See Resource provider.

    • Containers. Provides declarative and dynamic containers. See Containers.

    • Wiring. Injects dependencies into functions and methods. Helps integrate with other frameworks: Django, Flask, Aiohttp, Sanic, FastAPI, etc. See Wiring.

    • Asynchronous. Supports asynchronous injections. See Asynchronous injections.

    • Typing. Provides typing stubs, mypy-friendly. See Typing and mypy.

    • Performance. Fast. Written in Cython.

    • Maturity. Mature and production-ready. Well-tested, documented, and supported.

    from dependency_injector import containers, providers
    from dependency_injector.wiring import Provide, inject
    
    
    class Container(containers.DeclarativeContainer):
    
        config = providers.Configuration()
    
        api_client = providers.Singleton(
            ApiClient,
            api_key=config.api_key,
            timeout=config.timeout,
        )
    
        service = providers.Factory(
            Service,
            api_client=api_client,
        )
    
    
    @inject
    def main(service: Service = Provide[Container.service]) -> None:
        ...
    
    
    if __name__ == "__main__":
        container = Container()
        container.config.api_key.from_env("API_KEY", required=True)
        container.config.timeout.from_env("TIMEOUT", as_=int, default=5)
        container.wire(modules=[__name__])
    
        main()  # <-- dependency is injected automatically
    
        with container.api_client.override(mock.Mock()):
            main()  # <-- overridden dependency is injected automatically

    类方法注入

    from unittest import mock
    
    from dependency_injector import containers, providers
    from dependency_injector.wiring import Provide, inject
    
    from after import ApiClient, Service
    
    
    class Container(containers.DeclarativeContainer):
    
        config = providers.Configuration()
    
        api_client = providers.Singleton(
            ApiClient,
            api_key=config.api_key,
            timeout=config.timeout,
        )
    
        service = providers.Factory(
            Service,
            api_client=api_client,
        )
    
    
    @inject
    def main(service: Service = Provide[Container.service]) -> None:
        print("sss")
    
    
    class TEST:
        @inject
        def __init__(self, service: Service = Provide[Container.service]):
            # service.hello()
            self._service = service
            # print("test")
    
        @inject
        def run(self, service: Service = Provide[Container.service]):
            service.hello()
    
    
    
    if __name__ == "__main__":
        container = Container()
        # container.config.api_key.from_env("API_KEY", required=True)
        # container.config.timeout.from_env("TIMEOUT", as_=int, default=5)
        container.wire(modules=[__name__])
    
        test: TEST = TEST()
        test.run()
    
        main()  # <-- dependency is injected automatically
    
        with container.api_client.override(mock.Mock()):
            main()  # <-- overridden dependency is injected automatically

    service所在的after文件

    import os
    
    
    class ApiClient:
    
        def __init__(self, api_key: str, timeout: int) -> None:
            self.api_key = api_key  # <-- dependency is injected
            self.timeout = timeout  # <-- dependency is injected
    
    
    class Service:
    
        def __init__(self, api_client: ApiClient) -> None:
            self.api_client = api_client  # <-- dependency is injected
    
        def hello(self):
            print("hello")
    
    
    def main(service: Service) -> None:  # <-- dependency is injected
        ...
    
    
    if __name__ == "__main__":
        main(
            service=Service(
                api_client=ApiClient(
                    api_key=os.getenv("API_KEY"),
                    timeout=int(os.getenv("TIMEOUT")),
                ),
            ),
        )

     github例: https://github.com/fanqingsong/fastapi-ml-skeleton/blob/master/fastapi_modules/ioc_framework/implement.py

  • 相关阅读:
    面向对象初识
    day 20 异常
    day 16 正则表达式
    day 13 生成器,推导式
    CSS
    html页面编写
    DAY 17常用模块
    DAY16 模块和包的导入
    DAY15 模块
    DAY14 函数(三)
  • 原文地址:https://www.cnblogs.com/lightsong/p/16740024.html
Copyright © 2020-2023  润新知