# i.Python - 命名空間(namespace)
###### tags: `Python`
## 1.命名空間
* <font color="#0080FF">**三種類型的命名空間**</font>
| 類別 | 說明 |
| :------: | :-----------: |
| **內建(builtin)**| Python解釋器進行時,會建立一個名為 __ builtin __ 的模組,此模組包含所有內建函式,例如 len()、min()、max()、str() 等 |
| **全域(global)** | 建立其他模組時,模組所帶的命名空間被稱為全域命名空間,放在這個空間中的變數即為「全域變數」 |
| **區域(local)** | 呼叫函式時,Python 會為這個函式建立一個區域命名空間,</br>放在這個空間中的變數即為「區域變數」,</br>函式結束後,這個命名空間會隨之刪除 |
## 2.命名空間相關操作
* <font color="#0080FF">**查詢區域 ( local ) 命名空間**</font>
```python=+
locals() #因為沒有建立變數或引入函式,因此內容和global()相似
```
> ```{'__name__': '__main__','__doc__': 'Automatically created module for IPython interactive environment','__package__': None,'__loader__': None,'__spec__': None,'__builtin__': <module 'builtins' (built-in)>,'__builtins__': <module 'builtins' (built-in)>,'_ih': ['', 'locals()'],'_oh': {},...}```
##
* <font color="#0080FF">**查詢全域 ( global ) 命名空間**</font>
```python=+
globals() #因為沒有建立變數或引入函式,因此內容和locals()相似
```
> ```{'__name__': '__main__','__doc__': 'Automatically created module for IPython interactive environment','__package__': None,'__loader__': None,'__spec__': None,'__builtin__': <module 'builtins' (built-in)>,'__builtins__': <module 'builtins' (built-in)>,'_ih': ['', 'locals()', 'globals()'],'_oh': {1: {...}},...}```
##
* <font color="#0080FF">**建立新變數並匯入模組**</font>
```python=+
z = 2
import math
from cmath import cos
globals() #因為有新變數,增加了一些新的數值
```
> ```{'__name__': '__main__',...,'_i': 'globals()','_ii': 'locals()','_iii': '','_i1': 'locals()','_1': {...},'_i2': 'globals()','_2': {...},'_i3': 'z = 2\nimport math\nfrom cmath import cos\n\nglobals()','z': 2,'math': <module 'math' (built-in)>,'cos': <function cmath.cos(z, /)>}```
##
* <font color="#0080FF">**將名稱從命名空間刪除**</font>
```python=+
del z,math,cos
globals() #命名空間看不到z,math,cos且模組內函式也變得不可用
math.ceil(3.4)
#重新匯入
import math
math.ceil(3.4)
```
> ```{'__name__': '__main__',...,'_i': 'del z,math,cos','_ii': 'z = 2\nimport math\nfrom cmath import cos\n\nglobals()','_iii': 'globals()','_i1': 'locals()','_1': {...},'_i2': 'globals()','_2': {...},'_i3': 'z = 2\nimport math\nfrom cmath import cos\n\nglobals()','_3': {...},'_i4': 'del z,math,cos','_i5': 'globals()'}```</br></br>
> ```NameError: name 'math' is not defined```</br>
> ```4```
##
* <font color="#0080FF">**查看函式內區域變數**</font>
```python=+
def f(x):
#可以看到模組函式f的位址
print('globals:',globals())
print('進入 local:',locals())
y = x
print('離開 local:',locals())
z = 2
f(z)
#locals() <-這裡使用locals()已看不到變數
```
> ```globals: {'__name__': '__main__',..., '_i': '', '_ii': '', '_iii': '', '_i1': "def f(x):\n print('globals:',globals())\n print('進入 local:',locals())\n y = x\n print('離開 local:',locals())\n \nz = 2\nf(z)", 'f': <function f at 0x00000205C393C438>, 'z': 2}```</br></br>
> ```進入 local: {'x': 2}```</br>
> ```離開 local: {'x': 2, 'y': 2}```
## 3.已匯入模組的命名空間
<font color="#0080FF">**scopetest.py**</font>
```python=+
'''scopetest - 可視範圍測試模組'''
v = 6
def f(x):
'''f - scope test function'''
print('global: ',list(globals().keys()))
print('進入 local: ',locals())
y = x
w = v
print('離開 local: ',locals().keys())
```
##
* <font color="#0080FF">**<!!>模組內名稱的可視範圍**</font>
> <font color="#EA0000">**模組內可視的globals全域命名空間、locals區域命名空間,僅包含該模組內的 (不含主程式)**</font>
```python=+
import scopetest
z = 2
scopetest.f(z)
#命名空間不包含交談模式中建立的變數z,因此無須擔心
#模組外部的名稱會影響內部程式碼的運作
```
> ```global: ['__name__', '__doc__', '__package__', '__loader__', '__spec__', '__file__', '__cached__', '__builtins__', 'v', 'f']```</br></br>
> ```進入 local: {'x': 2}```</br>
> ```離開 local: dict_keys(['x', 'y', 'w'])```
## 4.<!!>從模組 import 變數容易發生的問題
<font color="#0080FF">**counter.py**</font>
```python=+
num = 0
def add():
global num
num += 1
```
##
* <font color="#0080FF">**使用 import 匯入**</font>
```python=+
import counter
print(counter.num)
counter.add()
print(counter.num)
```
> ```0```</br>
> ```1```
##
* <font color="#0080FF">**<!!>用 from ... import ... 匯入**</font>
```python=+
from counter import num,add #直接掛在主程式命名空間中,因此這裡的num,add屬於主程式
print(num)
add() #增加的是模組內全域變數的num
print(num)
import counter
print(counter.num) #模組內的num實際上有增加
```
> ```0```</br>
> ```0```</br>
> ```1```
## <!!>5.建立與內建函式同名的變數
* <font color="#0080FF">**<!!>全域變數名稱覆蓋同名稱內建函式**</font>
```python=+
list('SUSHI RAMEN')
list = [1,3,5,7]
list('SUSHI RAMEN') #已被同名變數名稱覆蓋
del list #刪除全域命名空間的list
list('SUSHI RAMEN')
```
> ```['S', 'U', 'S', 'H', 'I', ' ', 'R', 'A', 'M', 'E', 'N']```</br>
> ```TypeError: 'list' object is not callable```</br>
> ```['S', 'U', 'S', 'H', 'I', ' ', 'R', 'A', 'M', 'E', 'N']```
##
* <font color="#0080FF">**相同名稱重複使用 (新值覆蓋舊值)**</font>
```python=+
import mymath #為先前撰寫的自訂模組
mymath = mymath.area # mymath參照到模組的 area 函式
mymath(3)
mymath.pi
```
> ```28.27431```</br>
> ```AttributeError: 'function' object has no attribute 'pi'```
## 6.其他常用及特殊的操作
* <font color="#0080FF">**查看函式內的說明文件**</font>
```python=+
help(max)
print(max.__doc__)
```
> ```Help on built-in function max in module builtins:```</br>
> ```max(...)```</br>
> ``` max(iterable, *[, default=obj, key=func]) -> value```</br>
> ``` max(arg1, arg2, *args, *[, key=func]) -> value```
> ```...```</br></br>
> ```max(iterable, *[, default=obj, key=func]) -> value```</br>
> ```max(arg1, arg2, *args, *[, key=func]) -> value```
> ```...```
##
* <font color="#0080FF">**用 dir() 列出模組內所有名稱**</font>
```python=+
dir(__builtins__)
```
> ```['ArithmeticError','AssertionError','AttributeError','BaseException','BlockingIOError','BrokenPipeError','BufferError','BytesWarning',...,'str','sum','super','tuple','type','vars','zip']```
##
* <font color="#0080FF">**用 dir() 變數名稱偵錯**</font>
```python=+
x1 = 6
xl = x1 - 2 #左邊名稱將數字 1 誤打成英文字母 l
x1
dir() #(important!)在沒有參數的情況下傳回區域命名空間中的名稱,1並加以排序
#最後面可以看到變數竟然有兩個!!
```
> ```6```</br>
> ```['In','Out','_','_1','_14',...,'mymath','quit','x1','xl']```
##
## 7.在主程式與不同模組間共享變數資料
<font color="#0080FF">**config.py**</font>
```python=+
n = 0 #config模組內,存放需要共享的變數n
```
##
<font color="#0080FF">**Pmodule.py**</font>
```python=+
import config #將config模組import進來
def add():
config.n += 1
```
##
* <font color="#0080FF">**<!!>在模組內引入模組,即可共享該模組的變數(看Pmodule.py)**</font>
```python=+
import config
import Pmodule
print(config.n)
Pmodule.add()
print(config.n) #共享變數n的值已經被Pmodule改變了
```
> ```0```</br>
> ```1```
## 時間戳記
> [name=ZEOxO][time=Tue, Sep 1, 2020 15:13 PM][color=#907bf7]
[回到上面](#1.命名空間)