Python Namespace and Scope

來源:互聯網
上載者:User

標籤:代碼   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

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.