重新定义python内置函数

时间:2016-12-09 20:31:02

标签: python python-2.7

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

def blah():
    str = "asdf asdf asdf"
    doStuff(str)

这似乎有效,即使str是内置函数,也不应该用作变量。

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

3 个答案:

答案 0 :(得分:4)

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

这里还有另一个警告/角落案例,在this question中有描述。本地表条目是在编译时创建的,而不是在运行时创建的,因此即使在为其分配str之前,也无法在函数中使用"asdf asdf asdf"的全局定义:

def blah():
    x = str(12)
    str = "asdf asdf asdf"
    doStuff(str)

将失败并显示UnboundLocalError

答案 1 :(得分:3)

  

这似乎有效,即使str是内置函数,也不应该用作变量。

是的,这是事实。 Python并不能阻止你在脚下射击自己。作为开发人员,您可以确保不要覆盖内置名称。

  

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

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

>>> def foo():
...     str = 0
...     return str
... 
>>> foo()
0
>>> str(0)
'0'
>>>

第一个示例有效,因为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
>>> 

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

>>> str = 0
>>> str
0
>>> import __builtins__
>>> str = __builtins__.str
>>> str
<type 'str'>
>>> str(0)
'0'
>>> 

另外,正如@Brad所罗门所说,你只需使用del str来恢复内置str值:

>>> str = 0
>>> str
0
>>> del str
>>> str
<class 'str'>
>>> 

答案 2 :(得分:-2)

在您的情况下,str只是一个变量,没有什么可以阻止您在该函数之外通常使用str()

>>> str = 'Hello world!'
>>> print str
Hello world!
str(str)
Traceback (most recent call last):
   File "<stdin>", line 1, in <module>
TypeError: 'str' object is not callable

编辑:

这是一个简单的演示:

def salut():
   str = 'Hello world!'
   return str
if __name__ == '__main__':
   s = salut()
   print str(s) #nothing prevents you from using 'str' outside 'salut()'