我正在研究一个python程序,作者编写了一个看起来像这样的函数
def blah():
str = "asdf asdf asdf"
doStuff(str)
这似乎有效,即使str是内置函数,也不应该用作变量。
这里到底发生了什么?我的猜测是str将不再可用作函数,而只是在他编写的blah()函数的范围内。那是对的吗?这不会在全球范围内重新定义,对吗?
答案 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()'