一个朋友在开始学习Python时被"烧掉",现在认为这种语言可能存在致命缺陷.
他正在使用库并更改了对象属性的值(库中的类),但他使用了错误的属性名称缩写.他花了很长时间才弄清楚出了什么问题.因此,他对Python的反对意味着它允许人们不小心向对象添加属性.
单元测试不能为此提供解决方案.一个人不会针对正在使用的API编写单元测试.可能有一个类的模拟,但模拟可能有相同的错误或关于属性名称的错误假设.
可以使用它__setattr__()
来防止这种情况,但(据我所知),没有人这样做.
我能告诉我的朋友的唯一一件事就是,经过几年的全程编写Python代码,我不记得曾经被这个烧过.我还能告诉他什么?
"改变了对象属性的值"可能导致问题.这是众所周知的.你也知道,现在也是.这并没有起诉语言.它只是说你已经学会了动态语言编程的重要课程.
单元测试绝对发现了这一点.您不必强制模拟所有库类.有些人说,当它完全隔离测试时,它只是一个单元测试.这太傻了.您必须信任库模块 - 这是您的架构的一个功能.而不是模仿它们,只需使用它们.(为您自己新开发的库编写模拟非常重要.模拟进行昂贵API调用的库也很重要.)
在大多数情况下,您可以(并且应该)使用真实的库模块测试您的类.这将找到拼写错误的属性名称.
此外,既然您知道属性是动态的,那么验证属性是否存在非常容易.怎么样?
在编写太多代码之前,使用交互式Python来探索类.
请记住,Python不是Java,它不是C.您可以交互式执行Python,并在拼写错误时立即确定.编写大量代码而不进行任何交互式确认 - 简单地说 - 使用Python的错误方法.
一点点交互式探索将找到拼写错误的属性名称.
最后 - 对于您自己的类 - 您可以将可更新属性包装为属性.这样可以更轻松地调试任何拼写错误的属性名称.再次,你知道检查这个.您可以使用交互式开发来确认属性名称.
四处乱窜__setattr__
会产生问题.在某些情况下,我们实际上需要向对象添加属性.为什么?它比为一个特殊情况创建一个完整的子类更简单,我们必须维护更多的状态信息.
你可以说的其他事情:
我被一个C程序烧毁了,因为这个程序绝对无法工作______
.[在此处插入您想要的任何已知C语言问题.没有数组边界检查,例如]这是否使C致命有缺陷?
我被DBA烧毁了,他改变了一个列名并且所有的SQL都破了.单元测试所有这些都很痛苦.这是否会使关系数据库存在致命缺陷?
我被一个系统管理员烧毁了,他更改了目录的权限,我的应用程序崩溃了.几乎不可能找到.这会导致操作系统存在致命缺陷吗?
我被一个COBOL程序烧毁,有人改变了字帖,忘了重新编译程序,我们无法调试它,因为源代码看起来很完美.然而,COBOL实际上存在致命缺陷,因此这不是一个好例子.
像pylint这样的代码分析器会在你外面添加一个属性时发出警告__init__
.PyDev对此有很好的支持.使用调试器也很容易找到这样的错误.
如果犯错误的可能性足以让他考虑一种"致命缺陷"的语言,我认为你不能说服他.使用一种语言你能做的越多,你对语言的错误就越多.这是一个灵活性的警告 - 但这对任何语言都是如此.
您可以使用__slots__
class属性来限制实例具有的属性.尝试设置未列出的属性会引发一个AttributeError
.子类化会产生一些复杂性.有关详细信息,请参阅Python数据模型参考.