通常在赋值时声明变量被视为VBScript或JavaScript中的最佳实践,例如,尽管允许这样做。
为什么Python强制您仅在使用它时创建变量?由于Python区分大小写不能导致错误,因为你错误拼写了一个变量的名字?
你会如何避免这种情况?
答案 0 :(得分:15)
这是“教学语言”对Python灵感的愚蠢神器,它通过完全消除“声明”的绊脚石,使语言更易于访问。无论出于何种原因(可能表示为“简单”),Python从未获得像VB的“Option Explicit”这样的可选限制来引入强制声明。是的,它可能是错误的来源,但正如其他答案所示,良好的程序员可以养成习惯,使他们能够弥补语言中的任何缺点 - 而且由于缺点,这是一个非常小的问题。
答案 1 :(得分:12)
如果你想要一个具有“锁定”实例属性的类,那就不难做出一个,例如:
class LockedDown(object):
__locked = False
def __setattr__(self, name, value):
if self.__locked:
if name[:2] != '__' and name not in self.__dict__:
raise ValueError("Can't set attribute %r" % name)
object.__setattr__(self, name, value)
def _dolock(self):
self.__locked = True
class Example(LockedDown):
def __init__(self):
self.mistakes = 0
self._dolock()
def onemore(self):
self.mistakes += 1
print self.mistakes
def reset(self):
self.mitsakes = 0
x = Example()
for i in range(3): x.onemore()
x.reset()
正如您所看到的,对x.onemore
的调用工作正常,但reset
因异常错误拼写mitsakes
而引发异常。这里的参与规则是__init__
必须将所有属性设置为初始值,然后调用self._dolock()
以禁止任何进一步添加属性。我正在豁免“超私有”属性(以__
开头的),这些属性在风格上应该很少使用,对于完全特定的角色,并且范围非常有限(使得在超级中发现拼写错误很容易)仔细检查,无论如何都需要确认超级私密的需要),但这是一种风格选择,容易扭转;类似地,选择使锁定状态“不可逆”(通过“正常”意味着 - 即需要非常明确的解决方法来绕过)。
这不适用于其他类型的名称,例如函数本地名称;再一次,没什么大不了的,因为每个函数都应该非常小,并且是一个完全独立的范围,很容易检查(如果你编写100行函数,你还有其他严重的问题; - )。
值得这么麻烦吗?不,因为半体面的单元测试显然应该最容易地捕获所有这样的拼写错误,作为彻底运用该类功能的自然副作用。换句话说,就好像你需要进行更多单元测试来捕获拼写错误一样:单元测试你无论如何都需要捕获琐碎的语义错误(逐个,+1在哪里 - 1表示等等,也已经记录了所有错别字。
罗伯特·马丁和布鲁斯·埃克尔7年前在单独和独立的文章中都阐述了这一点 - 埃克尔的博客现在暂时失效,但马丁的权利here,当埃克尔的网站恢复该文章应该是{{ 3}}。这篇论文是有争议的(例如,Jeff Attwood及其评论者对其进行辩论here),但有趣的是,Martin和Eckel都是C ++和Java等静态语言的知名专家(尽管有爱情事务)分别使用Ruby和Python),他们远远没有发现单元测试的重要性......以及良好的单元测试套件作为副作用如何使静态语言的冗余冗余顺便说一下,检查测试套件的一种方法是“错误注入”:系统地检查你的代码库,引入一个错误的拼写 - 运行测试以确保它们确实失败,如果它们没有添加一个确实失败,纠正拼写错误,重复一遍。可以相当好地自动化(不是“添加测试”部分,而是查找套件未涵盖的潜在错误),以及一些其他形式的错误注入(将每个整数常量逐个更改为还有一个,少一个;将每个<
更改为<=
等;将每个if
和while
条件交换为反向; ...),而其他形式的错误注入还需要更多的人类悟性。不幸的是,我不知道公开可用的错误注入框架套件(对于任何语言) - 可能会成为一个很酷的开源项目; - )。
答案 2 :(得分:9)
在python中,有必要考虑将变量声明为名称的绑定值。
尽量不要拼错它们,否则你会有新的拼写错误(假设你在谈论赋值语句 - 引用它们会引起异常)。
如果您正在谈论实例变量,那么之后您将无法使用它们。
例如,如果您有一个班级myclass
并且在其__init__
方法中写了self.myvar = 0
,那么尝试引用self.myvare
会导致错误,而不是给您默认值。
答案 3 :(得分:5)
Python只会在您使用它时强制您创建变量。您始终可以将None
绑定到名称,然后在其他地方使用该名称。
答案 4 :(得分:4)
为了避免错误拼写变量名称的情况,我使用带有自动完成功能的文本编辑器并绑定
python -c "import py_compile; py_compile.compile('{filename}')"
到保存文件时要调用的函数。
答案 5 :(得分:3)
测试。
示例,文件variable.py
:
#! /usr/bin/python
somevar = 5
然后,创建文件variable.txt
(以进行测试):
>>> import variables
>>> variables.somevar == 4
True
然后做:
python -m doctest variable.txt
得到:
**********************************************************************
File "variables.txt", line 2, in variables.test
Failed example:
variables.somevar == 4
Expected:
True
Got:
False
**********************************************************************
1 items had failures:
1 of 2 in variables.test
***Test Failed*** 1 failures.
这表示变量声明不正确。
尝试:
>>> import variables
>>> variables.someothervar == 5
True
请注意,变量的名称不相同。
**********************************************************************
File "variables.test", line 2, in variables.test
Failed example:
variables.someothervar == 5
Exception raised:
Traceback (most recent call last):
File "/usr/local/lib/python2.6/doctest.py", line 1241, in __run
compileflags, 1) in test.globs
File "<doctest variables.test[1]>", line 1, in <module>
variables.someothervar == 5
AttributeError: 'module' object has no attribute 'someothervar'
**********************************************************************
1 items had failures:
1 of 2 in variables.test
***Test Failed*** 1 failures.
这显示拼写错误的变量。
>>> import variables
>>> variables.somevar == 5
True
然后返回没有错误。
我已经做了足够的VBScript开发,知道错别字是变量名中的问题,而且足够的VBScript开发知道Option Explicit
充其量只是一个拐杖。 (&lt; - 12年的ASP VBScript经验告诉我艰难的方法。)
答案 6 :(得分:2)
如果您进行任何认真的开发,您将使用(集成)开发环境。 Pylint将成为其中的一部分,并告诉你所有的拼写错误。无需将这样的功能作为语言的一部分。
答案 7 :(得分:-1)
变量声明不会阻止错误。除了缺少变量声明之外,还会导致错误。
变量声明会阻止一种特定类型的错误,但会产生其他类型的错误。
<强>阻止即可。编写代码,尝试使用错误的数据类型设置(或更改)变量。
<强>原因即可。愚蠢的解决方法是将一些不相关的类型强制在一起,以便分配“正常工作”。示例:C语言union
。此外,变量声明迫使我们使用强制转换。这也迫使我们在编译时抑制演员阵容的警告,因为我们“知道”它将“正常工作”。它没有。
缺少变量声明不会导致错误。最常见的“威胁情景”是对变量的某种“错误分配”。
变量是否被“重用”?这是愚蠢但合法且有效。
程序的某些部分是否错误地指定了错误的类型?
这导致了一个微妙的问题“错误是什么意思?”在鸭式语言中,错误意味着“不提供正确的方法或属性”。这仍然模糊不清。具体来说,它意味着“将要求类型提供它没有的方法或属性。”这将引发异常,程序将停止。
在生产使用中提出未被捕获的异常是令人讨厌的并且显示缺乏质量。这是愚蠢的,但它也是一个检测到的,已知的故障模式,追溯到确切的根本原因。
“不能因为拼写错误的名字错误导致错误”
是。它可以。
但请考虑这个Java代码。
public static void maine( String[] argv ) {
int main;
int mian;
}
这里的拼写错误同样致命。静态类型的Java已经完成 nothing 以防止拼写错误的变量名称导致错误。