標籤:代碼 object outer sse glob ram 特性 with min
我感覺很多英文名詞翻譯過來可能會引起誤解,因為大家的背景各異,看過的書也不一樣,對名詞的理解也有差異,為了表述不會引起歧義,對於一些名詞,文中全都用英文。
name(也叫 identifier)只是 objects 的 Name。這個解釋跟沒有解釋一樣。但是在python中, 所有的東西都是一個 object。name 僅僅是對記憶體中 object 的引用。
比如,一個簡單的賦值操作 a = 2,這裡的 2 是儲存在記憶體中的一個object,a 則是對 2 的引用。我們可以用 python內建的函數 id() 去得到記憶體中對象的地址: 比如下面的代碼:
>>> a = 2>>> id(a)23159120>>> id(2)23159120>>>
從上面的代碼我們可以看出,object 2 在記憶體中的地址是 23159120,a 指向的 object 記憶體位址也是 23159120, 它們代表的是同一個object。下面在看幾個例子:
>>> a = 2>>> id(a)23159120>>> a += 1>>> id(a)23159096>>> id(3)23159096>>> id(2)23159120>>> b = 2>>> id(b)23159120
這裡發生了什嗎?用一張圖說話吧!
1 a = 2, 在記憶體中建立一個 object,a 指向這個 object。當執行 a += 1,記憶體中產生一個新的 object 3,然後 a 指向 object 3 。所以 a 和 3 的記憶體位址是一樣的。
2 b = 2,記憶體中已經存在 object 2了,直接將它的引用賦值給 b。
python 為什麼這麼做呢?效率!記憶體中已經存在2 這個object了,在建立一個是浪費記憶體,直接把2的引用給b就行了,沒必要重新建立一個。因此python中的 name 可以引用任何類型的object。這個會給有過 C java scala 編程經驗的人很大困惑。其實python中的name僅僅是對記憶體中object 引用,object 的類型是object,name 是不存在類型的。那麼 name 指向的類型是如何確定的呢? python運行時確定,這個就是python的強大之處,體現了它動態特性。
>>> a = 5>>> a = ‘Hello World!‘>>> a = [1,2,3]
上面的幾個例子在c/c++肯定是錯的,但是在python中這麼寫完全沒問題。因為python中一切皆是object,因此function也是object,所以name也可以指向function。
>>> def printHell():... print ‘Hello‘... >>> a = printHell()Hello
那麼什麼是 namespace 呢?
已經講過name是什麼了,下面來談談 namespace。
簡單的說, namespace 就是 name 集合。
在python中,你可以將 namespace 想象成 name 到 object 的映射。
不同的 namespace 可以同時存在,但是它們必須完全隔離開來,否則會造成衝突。
當我們啟動python 解譯器的時候會建立一個namespace,這個namespace含有python所有的內建 name,只要程式不退出,這個namespace就一直存在。因此我們在程式的任何地方都可以調用 id()和print()。每個module也建立它自己的global namespace。
這些不同的namespace是互相隔離的,因此,同樣的 name 可以存在不同的module中而不會引起衝突。
module 中有各種各樣 function 和 class。當調用一個 function 時,python會建立一個 local namespace, 這個function定義的所有 name 都在這個 local namespace中。同樣的, class 和 function也是一樣。
python 變數 scope
程式中雖然存在各種各樣的 namespace,但是我們的程式也許並不可能去訪問每一個 namspace。這個就是 scope 的概念。
scope就是不需要任何首碼名就可以訪問namespace中的name 的代碼塊。這句確實不好翻譯,原文為:Scope is the portion of the program from where a namespace can be accessed directly without any prefix. 一共有三種scope:
1 當前function的scope,其中含有 local name
2 模組scope,有 global name
3 最外層的scope,有 內建的 name
當一個name出現在function中,python先在 local namespace中搜尋它,然後是 global namespace,最後在 內建的 namespace,如果還找不到就報錯。
def outer_function(): b = 20 def inner_func(): c = 30a = 10
上面的代碼,a 在 global namespace 中,變數 b 在 function outer_function 的 local namespace 中, c 在 inner_function() 的local namespace 中。在 function inner_function 中,c 是 local namespace,b 是 nonlocal , a 是 global,我們可以給c賦值,但是對於 b 和 c 則是唯讀。
在 inner_function 中如果我們試圖給 b 賦予一個新的值,那麼python會在 local namespace 中建立一個name b,這個b和 out_function中的b是不同的。a 同理。請看下面這個例子:
>>> def out_function():... a = 20... def inner_function():... a = 30... print ‘a = %s‘ % a... inner_function()... print ‘a = %s‘ % a... >>> out_function()a = 30a= 20>>> a = 10>>> out_function()a = 30a = 20>>> print ‘a = %s‘ % aa = 10
上面這個例子中的 a ,都是在各自不同 namespace 中。
如果我們將 a 聲明為 global,則所有的賦值和引用操作都將指向 global a。
>>> def outer_function():... global a... a = 20... def inner_function():... global a... a = 30... print ‘a = %s‘ % a... inner_function()... print ‘a = %s‘ % a... >>> a = 10>>> outer_function()a = 30a = 30>>> print(‘a =‘,a)a = 30
因為在local namespace 中將a聲明為 global,所以它會去global namespace中去尋找而不是自己重新建立,如果找不到就會報錯。
本文翻譯於:https://www.programiz.com/python-programming/namespace
Python Namespace and Scope