前情回顾
在我的上一篇文章中,我介绍了 IUPACker:一款将简化分子线性输入规范(SMILES)字符串转换为国际纯粹与应用化学联合会(IUPAC)名称的工具。我讲解了 SMILES 解析器、分子图以及用于官能团检测的模式引擎。现在是时候解决核心问题了:寻找官能团。
17 个函数与计数
当我开始为 IUPACker 构建官能团检测器时,我做了任何天真程序员都会做的事:我为每个基团写了一个函数。每一个,单独的。
python
def _is_carboxylic_acid(self, atom):
# 检查 C(=O)OH 模式
for neighbor in atom.bonds:
if neighbor is O and order == 2:
# 这是一个羰基!
if neighbor is O and order == 1 and neighbor.has_h:
# 这是一个羟基!
# ... 还有 20 行代码
def _is_ester(self, atom):
# 检查 C(=O)OR 模式
# ... 几乎相同的代码,略有不同
def _is_aldehyde(self, atom):
# 检查 CHO 模式
# ... 更多的类似代码
# ... 以及另外 14 个函数
这简直糟糕透顶。每增加一个新的官能团,都意味着复制、粘贴并微调相同的循环结构。代码重复冗余,更糟糕的是,添加新的官能团成了一种苦差事。每个函数都需要 20 到 30 行的样板代码。
我很快意识到,这种系统远不可持续。它完全背离了抽象的原则,让我深陷于混乱的代码之中。我一遍又一遍地编写相同的循环,只是改变了需要查找的键。
如果我能将这些模式定义为数据而不是代码会怎样?如果我能编写一个通用的匹配引擎,能够处理我抛给它的任何模式会怎样?
宣告我对声明式模式的热爱!
答案是什么?声明式模式!想法很简单:
将模式定义为一组键要求和原子条件
编写一个能够匹配任何模式的通用匹配引擎
通过添加新的模式定义(10 行代码)而不是新函数(30 行代码)来添加新的官能团。
现在的模式看起来是这样的:
免责声明:本文内容来自互联网,该文观点不代表本站观点。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌抄袭侵权/违法违规的内容,请到页面底部单击反馈,一经查实,本站将立刻删除。