python中的多级依赖注入

我有5个类,如下所示。执行从类 5 开始。在这里,依赖注入被用作侦听器对象传递给类的构造函数,然后该对象调用 listen() 方法。这部分很好。Bot


麻烦从现在开始。


从方法中,我调用另一个调用的方法,该方法位于类( 文件中)中。然后,该方法从 2 个不同的类和 中调用另外两个方法。listen()process()Processorprocessor.pyprocess()TokenizerCore


如您所见,所有这些都是耦合的,此处不使用依赖关系注入。我不知道该怎么做。


我已经尝试了python包和包的示例,但据我所知,这些示例与单级依赖关系有关,而不是这样的情况。dependency-injectorpinject


我曾想过在一个模块中创建所有必需的对象,并在需要时将其作为参数传递给所有类。但这似乎不是一个好习惯。


我能做些什么来解耦上面的代码?我应该如何进行模块化?


# core.py


class Core:

    def decide(self, data):

        """ Makes decisions based on input data """


        # blah blah

-


# tokenizer.py


import nltk


from nltk.corpus import stopwords

from nltk.tokenize import word_tokenize


stoplist = set(stopwords.words('english'))


class Tokenizer:

    def tokenize(self, query):

        """ Tokenize the input query string """

        tokenized_query = word_tokenize(query)

        clean_query = [w for w in tokenized_query if not w in stoplist]

        return clean_query

-


# processor.py


import tokenizer

import core


class Processor:

    def process(self, query):

        """ 

        Send the input query to tokenizer 

        tokenized input is send to the Core module for decision making

        """

        tokenized_input = tokenizer.Tokenizer().tokenize(query)

        core.Core().decide(tokenized_input)

-


# listener.py


import processor


class Listener:

    def listen(self):

        """ Continuosly listens to user input """

        while True:

            query=input()

            processor.Processor().process(query)

-


# bot.py


import listener


class Bot:

    def __init__(self, listener):

        listener.listen()


Bot(listener.Listener())


暮色呼如
浏览 108回答 2
2回答

ABOUTYOU

我认为你可以重新考虑这个设计,记住两个概念:Python 多重继承来设计你的类。使用 super() 和 Python 的方法解析顺序 (MRO) 在测试代码中注入类依赖项的模拟。关于第一点,您的类将如下所示:# core.pyclass Core:    def decide(self, data):        """ Makes decisions based on input data """        # blah blah# tokenizer.pyclass Tokenizer:    def tokenize(self, query):        """ Tokenize the input query string """        return query# processor.py# from tokenizer import Tokenizer# from core import Coreclass Processor(Core, Tokenizer):    def process(self, query):        """         Send the input query to tokenizer         tokenized input is send to the Core module for decision making        """        tokenized_input = super().tokenize(query)        super().decide(tokenized_input)# listener.py# from processor import Processorclass Listener(Processor):    def listen(self):        """ Continuosly listens to user input """        while True:            query=input()            super().process(query)# bot.py#from listener import Listenerclass Bot(Listener):    def start_listener(self):        super().listen()Bot().start_listener()通过这种OO设计和super()的使用,我们可以利用MRO在类的依赖项中注入模拟,我将展示如何在SUT(被测主题)中为其依赖项注入模拟。机器人和处理器的示例:class MockCore(Core):    def decide(self, data):        """ Here you can implement the behavior of the mock """class MockTokenizer(Tokenizer):    def tokenize(self, query):        """ Here you can implement the behavior of the mock """        return queryclass ProcessorSut(Processor, MockCore, MockTokenizer):    'Here we are injecting mocks for Processor dependencies'class Bot(Listener):    def start_listener(self):        super().listen()class MockListener(Listener):    def listen(self):        """ Here you can implement the behavior of the mock """        returnclass BotSut(Bot, MockListener):    'Here we are injecting a mock for the Listener dependency of Bot'看到我们的SUT类的MRO,我们可以理解为什么多重继承和super()的使用允许我们以这种方式注入模拟。机器人和处理器解决方案的结果 MRO:Help on class BotSut in module __main__:class BotSut(Bot, MockListener) |  Here we are injecting a mock for the Listener dependency of Bot |   |  Method resolution order: |      BotSut |      Bot |      MockListener |      Listener |      Processor |      Core |      Tokenizer |      builtins.object......Help on class ProcessorSut in module __main__:class ProcessorSut(Processor, MockCore, MockTokenizer) |  Here we are injecting mocks for Processor dependencies |   |  Method resolution order: |      ProcessorSut |      Processor |      MockCore |      Core |      MockTokenizer |      Tokenizer |      builtins.object

杨__羊羊

您可以将实用程序类设置为类属性:class Core:    def decide(self, data):        return Falseclass Tokenizer:    def tokenize(self, query):        return []  # ...class Processor:    tokenizer_class = Tokenizer    core_class = Core    def process(self, query):        tokenized_input = self.tokenizer_class().tokenize(query)        return self.core_class().decide(tokenized_input)class Listener:    processor_class = Processor    def listen(self):        while True:            query = input()            self.processor_class().process(query)然后,您可以使用测试框架的模拟/补丁功能,例如pytest的:monkeypatchdef test_foo(monkeypatch):    monkeypatch.setattr(Processor, 'tokenizer_class', FooTokenizer)    # etc...
打开App,查看更多内容
随时随地看视频慕课网APP

相关分类

Python