我今天发现了这个意外的时候,我注意到一个Python代码曾使用内置函数 all作为变量标识符来存储列表理解的结果,并没有抛出一个错误,所以我尝试以下:
type('abc')
Out[1]: str
type('abc') == str
Out[2]: True
str = int
type('abc') == str
Out[4]: False
type('abc')
Out[5]: str
type = [1,2,3]
type('abc')
---------------------------------------------------------------------------
TypeError Traceback (most recent call last)
<ipython-input-7-a74a7df76db1> in <module>()
----> 1 type('abc')
TypeError: 'list' object is not callable
Run Code Online (Sandbox Code Playgroud)
希望,当我问为什么在Python中允许这种行为时,这是一个有效的问题.
或者更好的是,我如何确保内置函数str是真的str而不是说,int所以str(123)不会被int(123)意外评估?
Python希望您对代码负责,这就是原因.Python没有私有属性,没有受保护的类,几乎没有限制你可以使用的名称.
是的,这意味着您可能会意外地重命名内置内容.为您的代码创建单元测试,使用linter,通常,您将很快学会发现意外使用您需要的内置代码.与您在代码中意外重复使用任何其他名称没有什么不同.
请注意,您只是屏蔽了内置名称; 名称查找无法在内置命名空间中找到全局下一个内容,因此如果设置str为其他内容,则会在内置命令之前找到.只需删除全局:
>>> str = 'foobar'
>>> isinstance('foobar', str)
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
TypeError: isinstance() arg 2 must be a class, type, or tuple of classes and types
>>> del str
>>> isinstance('foobar', str)
True
Run Code Online (Sandbox Code Playgroud)
另一种方法是使每个内置名称都成为一个保留关键字,这样你就可以获得一个允许的名称列表,并且没有灵活性来重新定义这些对象.例如,Python 2.7有144个这样的名字.
在此背景下,看到这个博客帖子由Guido van Rossum的为什么None,True而False现在关键字在Python 3:
因为你不能在任何Python程序中的任何地方使用它们作为变量或函数名称,所以使用Python的每个人都必须知道语言中的所有保留字,即使它们不需要它们.出于这个原因,我们试图保留较小的保留字列表,并且在向该语言添加新的保留字之前,核心开发人员会出现问题.