簡體   English   中英

重新定義python內置函數

[英]Redefining python built-in function

我正在研究一個python程序,作者編寫了一個看起來像這樣的函數

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

這似乎有效,即使str是內置函數,也不應該用作變量。

這里到底發生了什么? 我的猜測是str將不再可用作函數,但僅限於他編寫的blah()函數的范圍。 那是對的嗎? 這不會在全球范圍內重新定義str,對吧?

在內部,函數的局部變量表將包含str的條目,該條目將是該函數的本地條目。 您仍然可以通過做訪問函數內的內置類builtins.str在PY3和__builtin__.str中的Py2。 函數外部的任何代碼都不會看到任何函數的局部變量,因此內置類在其他地方可以安全使用。

這里還有另一個警告/角落案例,在這個問題中有描述。 本地表條目是在編譯時創建的,而不是在運行時創建的,因此即使在為其分配"asdf asdf asdf"之前,也無法在函數中使用str的全局定義:

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

將失敗並出現UnboundLocalError

這似乎有效,即使str是內置函數,也不應該用作變量。

是的,這是事實。 Python並不能阻止你在腳下射擊自己。 作為開發人員,您可以確保不要覆蓋內置名稱。

這里到底發生了什么? 我的猜測是str將不再可用作函數,但僅限於他編寫的blah()函數的范圍。 那是對的嗎? 這不會在全球范圍內重新定義str ,對吧?

你在這里也部分正確。 如果str的值被覆蓋為local,則僅影響當前作用域。 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函數(Python 2中的__builtins__ ),並將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'>
>>> 

在你的情況下, 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()'

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM