防止在Python中意外误导对象属性?

时间:2009-12-30 16:59:16

标签: python attributes

一位朋友在开始学习Python时被“烧掉”,现在认为语言为可能致命有缺陷。

他正在使用库并更改了对象属性的值(库中的类),但他使用了错误的属性名称缩写。他花了很长时间才弄清楚出了什么问题。因此,他对Python的反对是允许人们不小心将属性添加到对象中。

单元测试无法为此提供解决方案。一个人不会针对正在使用的API编写单元测试。可能有一个类的模拟,但模拟可能有相同的拼写错误或关于属性名称的错误假设。

可以使用__setattr__()来防范这种情况,但(据我所知),没有人这样做。

我唯一能告诉我的朋友的是,经过几年编写Python代码的全职工作,我不记得曾经被这个烧过。我还能告诉他什么?

8 个答案:

答案 0 :(得分:12)

“更改了对象属性的值”可能导致问题。这是众所周知的。你也知道,现在也是。这并没有起诉语言。它只是说你已经学会了动态语言编程的重要课程。

  1. 单元测试绝对可以发现这一点。您不必强制模拟所有库类。有些人说,在完全隔离测试时,它只是一个单元测试。这太傻了。您必须信任库模块 - 这是您的架构的一个功能。而不是模仿它们,只需使用它们。 (为您自己新开发的库编写模拟非常重要。模拟进行昂贵API调用的库也很重要。)

    在大多数情况下,您可以(并且应该)使用真实的库模块测试您的类。这将找到拼写错误的属性名称。

  2. 此外,既然您知道属性是动态的,那么验证属性是否存在非常容易。怎么样?

    在编写太多代码之前,使用交互式Python来探索类。

    请记住,Python不是Java,它不是C.您可以交互式执行Python,并在拼写错误时立即确定。编写大量代码而不进行任何交互式确认只是 - 使用Python的错误方法。

    一点点互动探索会找到拼写错误的属性名称。

  3. 最后 - 对于您自己的类 - 您可以将可更新属性包装为属性。这样可以更轻松地调试任何拼写错误的属性名称。再次,你知道检查这个。您可以使用交互式开发来确认属性名称。

  4. 围绕__setattr__进行讨论会产生问题。在某些情况下,我们实际上需要向对象添加属性。为什么?它比为一个特殊情况创建一个完整的子类更简单,我们必须维护更多的状态信息。


    你可以说的其他事情:

    由于______,我被一个绝对无法工作的C程序烧毁了。 [在此处插入您想要的任何已知C语言问题。没有数组边界检查,例如]这是否会导致C致命缺陷?

    我被DBA烧毁了,他更改了一个列名并且所有SQL都崩溃了。单元测试所有这些都很痛苦。这是否会使关系数据库存在致命缺陷?

    我被系统管理员烧毁了,他更改了目录的权限,我的应用程序崩溃了。几乎不可能找到。这会导致操作系统存在致命缺陷吗?

    我被一个COBOL程序烧毁,有人改变了字帖,忘了重新编译程序,我们无法调试它,因为源代码看起来很完美。然而,COBOL实际上 存在致命缺陷,所以这不是一个好例子。

答案 1 :(得分:7)

pylint之类的代码分析器会在__init__之外添加属性时向您发出警告。 PyDev对此有很好的支持。使用调试器也很容易找到这样的错误。

答案 2 :(得分:5)

如果犯错误的可能性足以让他考虑一种“致命缺陷”的语言,我认为你不能说服他。使用该语言越多,使用该语言就越能错误。这是一个灵活性的警告 - 但对任何语言都是如此。

答案 3 :(得分:5)

您可以使用__slots__ class属性来限制实例具有的属性。尝试设置未按列表列出的属性将引发AttributeError。子类化会产生一些复杂性。有关详细信息,请参阅Python data model reference

答案 4 :(得分:2)

pylintpychecker这样的工具可以检测到这一点。

答案 5 :(得分:1)

他有效地排除了一整套编程语言 - 动态类型语言 - 因为学到了一个很难的经验教训。如果他愿意,他只能使用静态类型的语言,并且作为程序员仍然具有非常富有成效的职业生涯,但他肯定会对他们产生深深的挫败感。那么他会断定他们是致命的吗?

答案 6 :(得分:1)

我认为你的朋友错误地用语言表达了他的挫败感。他真正的问题是缺乏调试技术。教他如何将程序分解成小块以检查输出。就像手动单元测试一样,这样就可以找到任何不一致的地方,并且可以证明或丢弃任何假设。

答案 7 :(得分:0)

我第一次开始时遇到过类似的Python体验...花了我3个月的时间来克服它。有一个发出警告的工具会很好......