命名空間,英文名字:namespaces
在研習命名空間以前,請打開在python的交互模式下,輸入:import this
~~~
>>> import this
The Zen of Python, by Tim Peters
Beautiful is better than ugly.
Explicit is better than implicit.
Simple is better than complex.
Complex is better than complicated.
Flat is better than nested.
Sparse is better than dense.
Readability counts.
Special cases aren't special enough to break the rules.
Although practicality beats purity.
Errors should never pass silently.
Unless explicitly silenced.
In the face of ambiguity, refuse the temptation to guess.
There should be one-- and preferably only one --obvious way to do it.
Although that way may not be obvious at first unless you're Dutch.
Now is better than never.
Although never is often better than *right* now.
If the implementation is hard to explain, it's a bad idea.
If the implementation is easy to explain, it may be a good idea.
Namespaces are one honking great idea -- let's do more of those!
~~~
這里列位看到的就是所謂《python之禪》,在本教程的[第零部分:嘮叨一些關于Python的事情](https://github.com/qiwsir/ITArticles/blob/master/BasicPython/001.md)有專門的翻譯,這里再次列出,是要引用其中的一句話。請看官看最后一句: Namespaces are one honking great idea -- let's do more of those!
這是為了向看官說明Namespaces、命名空間值重要性。
## 什么是命名空間
從“一切皆為對象”開始說起吧。對象,很多時候我們直接使用它并不方便,因此要給它取一個名字。打個比方,有這樣一個物種,它是哺乳綱靈長目人科人屬智人種,這就是所謂的對象,但是,在平時提及這個對象的時候,總是要說“哺乳綱靈長目人科人屬智人種”,是不是太麻煩了?于是聰明的這個物種就為這個世界上的各種對象命名,例如將“哺乳綱靈長目人科人屬智人種”這個對象命名為“人”。
在編程中也是如此,前面在講述變量相關知識的時候已經說明了變量和引用對象的關系。
~~~
>>> a = 7
>>> id(7)
137589400
>>> id(a)
137589400
>>> id(7)==id(a)
True
~~~
看這個例子。7就是一個計算機內存中存在的對象,用id()這個內置函數可以查看7在內存(在RAM)中的地址。a 就是為這個對象預備的名字,如前面所講的,它與內存中的一個編號為137589400的對象關聯,或者說引用了這個對象,這個對象就是7.
如果做了下面的操作:
~~~
>>> a = a+1
>>> id(a)
137589388
>>> a
8
>>> id(8)
137589388
~~~
其實,上面操作中的a+1完成的是a引用的對象7+1,只不過是順著對象7的命名a導入了對象7罷了,這樣就在內存中建立了一個新的對象8,同樣通過id()函數查看到內存中的地址,通過地址可以看到,這時候的a又自動引用對象8了.
~~~
>>> id(7) #對象7在內存中的地址沒變
137589400
>>> b = 7 #b引用此對象
>>> id(b)
137589400
~~~
上面a轉換引用對象的過程,是自動完成的。而當b=7的時候,并不是在內存中從新建立一個對象7,而是b引用了已有的對象。這就是python的所謂動態語言的特點。
[](https://github.com/qiwsir/ITArticles/blob/master/Pictures/22101.png)
當然,可以給任何對象取名字,或者說為任何對象都可以建立一個所引用的變量。比如函數、類都可以,此處不贅述,前面已經多次用到了。
現在已經又一次明確了,每個名稱(命名)——英文中的NAME有動詞和名字兩種,所以,由于中文的特點,似乎怎么說都可以,只要明白所指,因為中文是強調語境的語言——都與某個對象有對應關系。那么所謂的命名空間,就是這些命名(名稱)的集合,它們分別與相應的對象有對應關系。
用一句比較學術化的語言說:
**命名空間是從所定義的命名到對象的映射集合。**
不同的命名空間,可以同時存在,當彼此相互獨立互不干擾。
命名空間因為對象的不同,也有所區別,可以分為如下幾種:
* 內置命名空間(Built-in Namespaces):Python運行起來,它們就存在了。內置函數的命名空間都屬于內置命名空間,所以,我們可以在任何程序中直接運行它們,比如前面的id(),不需要做什么操作,拿過來就直接使用了。
* 全局命名空間(Module:Global Namespaces):每個模塊創建它自己所擁有的全局命名空間,不同模塊的全局命名空間彼此獨立,不同模塊中相同名稱的命名空間,也會因為模塊的不同而不相互干擾。
* 本地命名空間(Function&Class: Local Namespaces):模塊中有函數或者類,每個函數或者類所定義的命名空間就是本地命名空間。如果函數返回了結果或者拋出異常,則本地命名空間也結束了。
從網上盜取了一張圖,展示一下上述三種命名空間的關系
[](https://github.com/qiwsir/ITArticles/blob/master/Pictures/22102.png)
那么程序在查詢上述三種命名空間的時候,就按照從里到外的順序,即:Local Namespaces --> Global Namesspaces --> Built-in Namesspaces
還要補充說一下,既然命名空間中存在著命名和對象的映射,不知道看官看到這句話能想到什么?啟發一下,回憶以往學過的那種類型數據也存在對應關系呢?字典,就是那個dictionary,是“鍵值”對應的,例如:{"name":"qiwsir","lang":"python"}
~~~
>>> def foo(num,str):
... name = "qiwsir"
... print locals()
...
>>> foo(221,"qiwsir.github.io")
{'num': 221, 'name': 'qiwsir', 'str': 'qiwsir.github.io'}
>>>
~~~
這是一個訪問本地命名空間的方法,用print locals() 完成,從這個結果中不難看出,所謂的命名空間中的數據存儲結構和dictionary是一樣的。
根據習慣,看官估計已經猜測到了,如果訪問全局命名空間,可以使用 print globals()。
## 作用域
作用域是指 Python 程序可以直接訪問到的命名空間。“直接訪問”在這里意味著訪問命名空間中的命名時無需加入附加的修飾符。(這句話是從網上抄來的)
程序也是按照搜索命名空間的順序,搜索相應空間的能夠訪問到的作用域。
~~~
def outer_foo():
b = 20
def inner_foo():
c = 30
a = 10
~~~
加入我現在位于inner_foo()函數內,那么c對我來講就在本地作用域,而b和a就不是。如果我在inner_foo()內再做:b=50,這其實是在本地命名空間內新創建了對象,和上一層中的b=20毫不相干。可以看下面的例子:
~~~
#!/usr/bin/env python
#coding:utf-8
def outer_foo():
a = 10
def inner_foo():
a = 20
print "inner_foo,a=",a #a=20
inner_foo()
print "outer_foo,a=",a #a=10
a = 30
outer_foo()
print "a=",a #a=30
#運行結果
inner_foo,a= 20
outer_foo,a= 10
a= 30
~~~
如果要將某個變量在任何地方都使用,且能夠關聯,那么在函數內就使用global 聲明,其實就是曾經講過的全局變量。請參考[《變量和參數》](https://github.com/qiwsir/ITArticles/blob/master/BasicPython/213.md)
- 第零部分 獨上高樓,望盡天涯路
- 嘮叨一些關于Python的事情
- 為什么要開設本欄目
- 第一部分 積小流,至江海
- Python環境安裝
- 集成開發環境(IDE)
- 數的類型和四則運算
- 啰嗦的除法
- 開始真正編程
- 初識永遠強大的函數
- 玩轉字符串(1):基本概念、字符轉義、字符串連接、變量與字符串關系
- 玩轉字符串(2)
- 玩轉字符串(3)
- 眼花繚亂的運算符
- 從if開始語句的征程
- 一個免費的實驗室
- 有容乃大的list(1)
- 有容乃大的list(2)
- 有容乃大的list(3)
- 有容乃大的list(4)
- list和str比較
- 畫圈還不簡單嗎
- 再深點,更懂list
- 字典,你還記得嗎?
- 字典的操作方法
- 有點簡約的元組
- 一二三,集合了
- 集合的關系
- Python數據類型總結
- 深入變量和引用對象
- 賦值,簡單也不簡單
- 坑爹的字符編碼
- 做一個小游戲
- 不要紅頭文件(1): open, write, close
- 不要紅頭文件(2): os.stat, closed, mode, read, readlines, readline
- 第二部分 窮千里目,上一層樓
- 正規地說一句話
- print能干的事情
- 從格式化表達式到方法
- 復習if語句
- 用while來循環
- 難以想象的for
- 關于循環的小伎倆
- 讓人歡喜讓人憂的迭代
- 大話題小函數(1)
- 大話題小函數(2)
- python文檔
- 重回函數
- 變量和參數
- 總結參數的傳遞
- 傳說中的函數條規
- 關于類的基本認識
- 編寫類之一創建實例
- 編寫類之二方法
- 編寫類之三子類
- 編寫類之四再論繼承
- 命名空間
- 類的細節
- Import 模塊
- 模塊的加載
- 私有和專有
- 折騰一下目錄: os.path.<attribute>
- 第三部分 昨夜西風,亭臺誰登
- 網站的結構:網站組成、MySQL數據庫的安裝和配置、MySQL的運行
- 通過Python連接數據庫:安裝python-MySQLdb,連接MySQL
- 用Pyton操作數據庫(1):建立連接和游標,并insert and commit
- 用Python操作數據庫(2)
- 用Python操作數據庫(3)
- python開發框架:框架介紹、Tornado安裝
- Hello,第一個網頁分析:tornado網站的基本結構剖析:improt模塊、RequestHandler, HTTPServer, Application, IOLoop
- 實例分析get和post:get()通過URL得到數據和post()通過get_argument()獲取數據
- 問候世界:利用GAE建立tornado框架網站
- 使用表單和模板:tornado模板self.render和模板變量傳遞
- 模板中的語法:tornado模板中的for,if,set等語法
- 靜態文件以及一個項目框架
- 模板轉義
- 第四部分 暮然回首,燈火闌珊處
- requests庫
- 比較json/dictionary的庫
- defaultdict 模塊和 namedtuple 模塊
- 第五部分 Python備忘錄
- 基本的(字面量)值
- 運算符
- 常用的內建函數
- 擴展閱讀(來自網絡文章)
- 人生苦短,我用Python