我知道命名一个与Python内置函数同名的变量是个坏主意.但是如果一个人不知道要避免的所有"禁忌"变量名称(例如list,set等等),是否有办法让Python至少阻止你(例如通过错误消息)破坏内置函数?
例如,下面的命令行4允许我覆盖/损坏内置函数,set()而不会阻止我/产生错误.(这个错误一直没有被注意到,直到它被set()调用到下面的命令行6.).理想情况下,我希望Python在命令行4停止我(而不是等到命令行6).
注意:以下执行是在Python 2.7(iPython)控制台中执行的.(Anaconda Spyder IDE).
In [1]: myset = set([1,2])
In [2]: print(myset)
set([1, 2])
In [3]: myset
Out[3]: {1, 2}
In [4]: set = set([3,4])
In [5]: print(set)
set([3, 4])
In [6]: set
Out[6]: {3, 4}
In [7]: myset2 = set([5,6])
Traceback (most recent call last):
File "<ipython-input-7-6f49577a7a45>", line 1, in <module>
myset2 = set([5,6])
TypeError: 'set' object is not callable
Run Code Online (Sandbox Code Playgroud)
背景:我正在遵循HackerRank Python Set Challenge的教程.本教程涉及创建一个变量valled set(与Python内置函数同名).我逐行完成了教程,并得到了"set object is not callable"错误.上述测试是由这项练习推动的.(更新:我联系了HackerRank支持,他们已经确认他们可能在创建具有内置名称的变量时出错了.)
正如其他人所说,Python 的哲学是允许用户“误用”事物,而不是试图想象和防止误用,因此没有内置类似的东西。但是,通过如此开放地被搞乱,Python 允许您以有限的方式实现您正在谈论的东西*。您可以用对象替换某些变量命名空间字典,以防止您最喜欢的变量被覆盖。(当然,如果这以意想不到的方式破坏了你的任何代码,你就会得到这两部分。)
为此,您需要使用诸如eval()、exec、execfile()、 或code.interact()、 或 override 之类的东西__import__()。这些允许您提供像字典一样的对象,用于存储变量。我们可以通过子类化创建一个“更安全”的替换字典dict:
class SafeGlobals(dict):
def __setitem__(self, name, value):
if hasattr(__builtins__, name) or name == '__builtins__':
raise SyntaxError('nope')
return super(SafeGlobals, self).__setitem__(name, value)
my_globals = SafeGlobals(__builtins__=__builtins)
Run Code Online (Sandbox Code Playgroud)
将my_globalsset 设置为当前命名空间,设置如下变量:
x = 3
Run Code Online (Sandbox Code Playgroud)
将翻译为以下内容:
my_globals['x'] = 3
Run Code Online (Sandbox Code Playgroud)
以下代码将执行一个 Python 文件,使用我们更安全的字典作为顶级命名空间:
execfile('safetyfirst.py', SafeGlobals(__builtins__=__builtins__))
Run Code Online (Sandbox Code Playgroud)
一个例子code.interact():
>>> code.interact(local=SafeGlobals(__builtins__=__builtins__))
Python 2.7.9 (default, Mar 1 2015, 12:57:24)
[GCC 4.9.2] on linux2
Type "help", "copyright", "credits" or "license" for more information.
(InteractiveConsole)
>>> x = 2
>>> x
2
>>> dict(y=5)
{'y': 5}
>>> dict = "hi"
Traceback (most recent call last):
File "<console>", line 1, in <module>
File "<stdin>", line 4, in __setitem__
SyntaxError: nope
Run Code Online (Sandbox Code Playgroud)
*不幸的是,这种方法非常有限。它只会阻止覆盖顶级命名空间中的内置函数。您可以随意覆盖其他命名空间中的内置函数:
>>> def f():
... set = 1
... return set
...
>>> f()
1
Run Code Online (Sandbox Code Playgroud)
| 归档时间: |
|
| 查看次数: |
8588 次 |
| 最近记录: |