<p>注意:以下代码适用于Python3.5或更高版本。<br/>
首先,将解析器的逻辑与通过解析器运行字符串的代码的逻辑分开。让我们从后者的代码开始:</p>
<pre><code>from typing import List
def run_parsers(message: str, parsers: List[BaseParser]) -> None:
for parser in parsers:
parser.parse_message(message)
</code></pre>
<p>注意:在最新的Python版本中,可以对代码进行注释。我之所以选择在这里这样做,是为了说明这个函数并不关心它得到什么类型的解析器。它需要一个<code>BaseParser</code>实例列表(包括从<code>BaseParser</code>继承的类的实例),然后在<code>message</code>上调用每个实例的<code>parse_sting</code>方法。这个函数不关心<code>parse_message</code>做什么。<br/>
接下来,您要为解析器对象定义一个API,以便<code>run_parsers</code>可以使用它们而不知道它们是如何工作的</p>
<pre><code>class BaseParser:
def __init__(self):
self.triggered = False
def parse_message(self, message: str):
raise NotImplementedError
</code></pre>
<p>如您所见<code>BaseParser</code>几乎没有逻辑,它只是说从我继承的人应该定义<code>parse_message</code>。而且,继承者得到一个<code>triggered</code>属性。<br/>
现在,让我们看看一个这样的继承者的代码</p>
<pre><code>class ImageParser:
def __init__(self):
super().__init__()
self.key_phrases = ('jpg', 'png')
def parse_message(self, message):
for phrase in self.key_phrases:
if phrase in message:
self.respond()
self.triggered = True
def respond(self):
do_something_here()
</code></pre>
<p>只要继承者遵循BaseInheriter设置的“规则”(即实现一个方法并拥有一个名为<code>triggered</code>的属性),<code>run_parsers</code>就会愉快地运行它们。<br/>
注意:<code>ImageParser</code>将<code>triggered</code>设置为True,这就是如何确定哪些解析器采取了某些操作。<br/>
最后,我们将<code>main</code>函数转换为上面的代码:</p>
<pre><code>def main():
message = 'how are you?'
parsers = [ImageParser(), IPParser()]
run_parsers(message, parsers)
if not any([parser.triggered for parser in parsers]):
show_help()
</code></pre>
<p>重要提示:确保阅读并使用<a href="https://pep8.org/" rel="nofollow noreferrer">pep8 guidelines</a>。面向对象的设计使应用程序的流程复杂化,并且您不希望通过提出自己的代码样式或约定而使事情进一步复杂化</p>