重新定义python内置函数

Dav*_*ave 5 python python-2.7

我正在使用python程序,作者编写了一个看起来像这样的函数

def blah():
    str = "asdf asdf asdf"
    doStuff(str)
Run Code Online (Sandbox Code Playgroud)

即使str是内置函数,也不应将其用作变量,这似乎可行。

这里到底发生了什么?我的猜测是str将不再可用作函数,而只能在他编写的blah()函数的范围内使用。那是对的吗?这不会在全球范围内重新定义str,对吗?

Chr*_*ean 6

这似乎有效,尽管 str 是内置函数并且不应该用作变量。

是的,确实如此。Python 并不能阻止你搬起石头砸自己的脚。作为开发人员,您有责任确保不覆盖内置名称。

这里到底发生了什么?我的猜测是 str 将不再可用作函数,而只能在blah()他编写的函数范围内使用。那是对的吗?这不会str在全球范围内重新定义,对吗?

你在这里也部分正确。如果 的值str被本地覆盖,那么只有当前范围受到影响。的全球价值str保持不变。但是,如果在全局str作用域中进行覆盖,则会影响所有子作用域。这背后的原因是 Python 解释器如何在运行时编译值。可以使用一个简单的示例来观察此行为:

>>> def foo():
...     str = 0
...     return str
... 
>>> foo()
0
>>> str(0)
'0'
>>>
Run Code Online (Sandbox Code Playgroud)

第一个示例之所以有效,str是因为仅在 的范围内被覆盖foo()。然而,第二个示例失败了,因为str被全局覆盖:

>>> str = 0
>>> def foo():
...     return str(0)
... 
>>> foo()
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
  File "<stdin>", line 2, in foo
TypeError: 'int' object is not callable
>>> 
Run Code Online (Sandbox Code Playgroud)

不过,您始终可以导入builtins__builtins__在 Python 2 中),并将 的值重置str为其原始含义:

>>> str = 0
>>> str
0
>>> import __builtins__
>>> str = __builtins__.str
>>> str
<type 'str'>
>>> str(0)
'0'
>>> 
Run Code Online (Sandbox Code Playgroud)

另外,正如 @Brad Solomon 所说,您可以简单地使用del str来恢复内置str值:

>>> str = 0
>>> str
0
>>> del str
>>> str
<class 'str'>
>>> 
Run Code Online (Sandbox Code Playgroud)


Mad*_*ist 5

在内部,函数的局部变量表将包含的条目str,该条目在该函数中是局部的。您仍然可以通过builtins.str在Py3和__builtin__.strPy2中进行操作来访问函数中的内置类。函数外部的任何代码都不会看到函数的任何局部变量,因此内置类可以在其他地方安全使用。

这里还有另一个警告/拐角的情况,此问题对此进行了描述。本地表条目是在编译时而不是在运行时创建的,因此str即使在分配"asdf asdf asdf"给函数之前,也无法在函数中使用的全局定义:

def blah():
    x = str(12)
    str = "asdf asdf asdf"
    doStuff(str)
Run Code Online (Sandbox Code Playgroud)

将以失败UnboundLocalError

  • builtins.str 抛出`name'builtins'未定义`,显然你需要使用`__builtins__.str`来调用它。我正在使用Python 3.7.5。 (2认同)