iT邦幫忙

第 11 屆 iThome 鐵人賽

DAY 20
0

不管是多型或函式閉包都要考慮物件本身的靈活性 但初學者常會忽略作用域的觀念


作用域是什麼?

可以想成是一個函數或物件裡的環境 任何封裝的程式代碼或內建函式都可看成一個作用域。
而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()

https://ithelp.ithome.com.tw/upload/images/20190922/20117399iG6A8QZZ9X.png
這時就觸動了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()

locals() & globals()

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。

用法為:type(class , 定義物件class() , 物件方法屬性)

def hey(self):
    print("123123")
#type(class , 定義物件class() , 物件方法屬性)
omg = type("omg",(object,),{'hey':hey})    
b=omg()
b.hey()

上一篇
[D19] python資料型別
下一篇
[D21] python遞迴
系列文
從寫程式到脫離菜雞的歷練(以python為主的資處與檔案權限)32
圖片
  直播研討會
圖片
{{ item.channelVendor }} {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

尚未有邦友留言

立即登入留言