重新定义python内置函数

2024-05-16 12:32:35 发布

您现在位置:Python中文网/ 问答频道 /正文

我正在开发一个python程序,作者编写了一个如下所示的函数

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

尽管str是一个内置函数,不应该用作变量,但这似乎是可行的。

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


Tags: 函数程序定义def作者作用域内置全球
3条回答

在您的例子中,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()'

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

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

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

将以UnboundLocalError失败。

This seems to work, even though str is a built in function and shouldn't be used as a variable.

是的,那是真的。Python不会阻止你射中自己的脚。作为开发人员,您需要确保不覆盖内置名称。

What is actually happening here? My guess is str will no longer be usable as a function, but only in the scope of the blah() function he's written. Is that correct? This won't redefine str globally, right?

你在这里也有一部分是正确的。如果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
>>> 

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

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

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

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

相关问题 更多 >