正确的答案是“都不”hasattr 提供功能,但它可能是所有选项中最糟糕的。
我们使用 python 的面向对象特性,因为它可以工作。OO 分析永远不会准确并且经常令人困惑,但是我们使用类层次结构,因为我们知道它们可以帮助人们更快地更好地工作。人们掌握对象,一个好的对象模型可以帮助编码人员更快地改变事物并且减少错误。正确的代码最终聚集在正确的位置。对象:
- 可以直接使用而不考虑存在哪个实现
- 明确需要更改的内容和位置
- 将某些功能的更改与某些其他功能的更改隔离开来——您可以修复 X 而不必担心会破坏 Y
hasattr 与 isinstance
必须使用 isinstance 或 hasattr 表明对象模型已损坏或我们使用不正确。正确的做法是修复对象模型或改变我们使用它的方式。这两个构造具有相同的效果,并且在命令式“我需要代码来执行此操作”意义上它们是等效的。结构上有很大的不同。在第一次遇到这种方法时(或在做了几个月的其他事情之后),isinstance 传达了更多关于实际发生的事情和其他可能的信息。Hasattr 不会“告诉”你任何事情。
悠久的开发历史使我们远离了 FORTRAN 和带有大量“我是谁”开关的代码。我们选择使用对象是因为我们知道它们有助于使代码更易于使用。通过选择 hasattr,我们提供了功能,但没有任何东西是固定的,代码比我们开始之前更糟糕。将来添加或更改此功能时,我们将不得不处理分组不均且至少具有两个组织原则的代码,其中一些在“应该”的地方,其余的则随机分散在其他地方。没有什么可以使它连贯一致。这不是一个错误,而是散布在通过你的 hasattr 的任何执行路径上的潜在错误的雷区。
因此,如果有任何选择,顺序是:
- 使用对象模型或修复它,或者至少弄清楚它有什么问题以及如何修复它
- 使用 isinstance
- 不要使用 hasattr