Python基礎-做用域和命名空間(Scope and Namespace)

在Python中,對象是獨立的,不一樣做用域中的不一樣名字均可以被綁定在同一個對象上,固然對這個對象的修改會影響全部的引用。賦值操做就是名字和對象的綁定或重綁定。這和C++中的引用是同樣的。html

1,基礎概念python

1.1 命名空間(namespace)  app

namespace is a mapping from names to objects函數

命名空間是名字和對象的映射。也就是能夠把一個namespace理解爲一個字典,實際上不少當前的Python實現namespace就是用的字典。各個命名空間是獨立的,沒有任何關係的,因此一個命名空間中不能有重名,但不一樣的命名空間是能夠重名而沒有任何影響。測試

那麼哪些能夠是一個namespace呢,好比Python的built-in names(包括內置函數,內置常量,內置類型);一個模塊的global names(這個模塊定義的函數,類,變量);一個函數的全部local names;還有一個類對象的全部屬性(數據成員,成員函數)都組成一個命名空間。ui

命名空間都是有建立時間和生存期的。對於Python built-in names組成的命名空間,它在Python解釋器啓動的時候被建立,在解釋器退出的時候才被刪除;對於一個Python模塊的global namespace,它在這個module被import的時候建立,在解釋器退出的時候退出;對於一個函數的local namespace,它在函數每次被調用的時候建立,函數返回的時候被刪除。spa

[總結]一個模塊的引入,函數的調用,類的定義都會引入命名空間,函數中的再定義函數,類中的成員函數定義會在局部namespace中再次引入局部namespace。rest

 

1.2 做用域(scope)  code

scope is a textual region of a Python program where a namespace is directly accessible.htm

做用域是Python程序(文本)的某一段或某些段,在這些地方,某個命名空間中的名字能夠被直接引用。這個做用域就是這個命名空間的做用域。

一個Python程序的幾個做用域:

  1. 最裏面的局部做用域
  2. 外層函數的局部做用域
  3. 模塊的全局做用域
  4. 包含Python內置對象的最外層做用域

 

關於做用域,參加Python基礎-函數這片博客中2小節的例子。

 

1.3 賦值(assignment)  

Assignments do not copy data — they just bind names to objects.

賦值操做不會拷貝,只是把名字和對象作一個綁定。也就是賦值語句是起一個綁定或重綁定的做用(bind or rebind)。函數調用的參數傳遞是賦值,不是拷貝。

 

2,global和nonlocal語句

global語句用來聲明一系列變量,這些變量會引用到當前模塊的全局命名空間的變量(module-level namespace),若是該變量沒有定義,也會在全局空間中添加這個變量。

global var1, var2

 nonlocal語句(nonlocal是Python3.2引入的)

Python2.7中尚未nonlocal語句。nonlocal語句用來聲明一系列的變量,這個聲明會從聲明處從裏到外的namespace去搜尋這個變量(the nearest enclosing scope),直到模塊的全局域(不包括全局域),找到了則引用這個命名空間的這個名字和對象,若做賦值操做,則直接改變外層域中的這個名字的綁定。nonlocal語句聲明的變量不會在當前scope的namespace字典中加入一個key-value對,若是在外層域中沒有找到,則以下報錯。

>>>SyntaxError: no binding for nonlocal 'spam' found

 

 一個nonlocal和global的測試例子

 1 def test():
 2     def do_local():
 3         spam = "local spam"
 4     def do_nonlocal():
 5         nonlocal spam    
6
spam = "nonlocal spam" 7 def do_global(): 8 global spam 9 spam = "global spam" 10 spam = "test spam" 11 do_local() 12 print("after local assignment:", spam) #輸出:test spam 13 do_nonlocal() 14 print("after nonlocal asssignment:", spam) #輸出:nonlocal spam 15 do_global() 16 print("after global assignment:", spam) #輸出:nonlocal spam 17 18 test() 19 print("in global scope:", spam) #輸出:global spam

第5行的語句:nonlocal spam 沒有在函數do_nonlocal()的域中建立一個變量,而是去引用到了外層的,10行定義的spam。

第8行的global spam,在全局域中建立了一個name,9行將其綁定在字符串常量對象"global spam"上。

 

跟進一步測試nonlocal

 1 def test():
 2     def do_nonlocal():
 3         nonlocal spam
 4         def do_nonlocal2():
 5             nonlocal spam
 6             spam = "nonlocal2 spam"  #修改了test()中spam的綁定
 7         do_nonlocal2()
 8     spam = "test spam"
 9     do_nonlocal()
10     print("after nonlocal2 asssignment:", spam)  #輸出:nonlocal2 spam 11 test()

do_nonlocal2()中的spam引用的是其外面的二層,也就是test()函數域中的spam。

 

 

參考:

http://docs.python.org/3.3/tutorial/classes.html#python-scopes-and-namespaces   Python文檔

http://docs.python.org/3.2/reference/simple_stmts.html  Python文檔-simple statement

相關文章
相關標籤/搜索