不管是多型或函式閉包都要考慮物件本身的靈活性 但初學者常會忽略作用域的觀念
可以想成是一個函數或物件裡的環境 任何封裝的程式代碼或內建函式都可看成一個作用域。
而4大作用域之間的行為不受影響(只影響調用順序)
A. Local == 區域(局部) 含任何自訂函式 , 物件
B. Enclosing == 巢函式(閉包)外的函數區域內
C. Built-in == 內建作用域(為固定域) ex:if/for/while...
D. Global == 全域 含外部所有自訂變數
查詢順序:就是python執行時的調用順序
A>B>D>C
套用在變數上也是同樣的查詢順序,變數作用域可是使用閉包的重要觀念呢,用python舉個例:
a = 5
i = 10
print(i) #外部 Global
for i in range(0,a): #迴圈 Built-in
i+=1
print(i)
外部i是D域;而迴圈為C域。已經定義了i為10 為何不從10開始連加呢?
因為作用域之間是不受行為影響的 所以就算i已被定義為10,迴圈內的i仍不受影響。
巢函式的狀況:
def outfc():
a = 200
print(a) #200
b = 100
def infc():
print(b) #100
b = 50
return b #50
infc()
print(b)
outfc()
這時就觸動了4大區域的Enclosing區域,可把此結構假設成閉包。
我們知道閉包有封裝的功用,所以自然就無法改變變數值。所以要用『nonlocal』將它變成專為閉包處理的變數。
def outfc():
a = 200
print(a) #200
b = 100
def infc():
nonlocal b #宣告為封裝變數
print(b) #100
b = 50
return b #50
infc()
print(b)
outfc()
globals() == 把所有正在使用的全域變數印出
locals() == 把所有正在使用的區域變數印出
想知道此區域(作用域)有多少區域變數,就可使用locals()
class print_number:
def www(self, i=1):
self.__i = i
def www_add(self):
return (self.__i)**500
print(locals())
d = print_number()
d.www()
print(d.www_add())
d.i = 0xABCDEFEDCBA987987
print(d.www_add())
用法為:type(class , 定義物件class() , 物件方法屬性)
def hey(self):
print("123123")
#type(class , 定義物件class() , 物件方法屬性)
omg = type("omg",(object,),{'hey':hey})
b=omg()
b.hey()