修改全域性變數時,可變型別和不可變型別的區別

real-admin發表於2018-12-01

先說結論:

巢狀函式(如閉包,修飾器等),需要修改全域性變數時,如果全域性變數是不可變型別,那麼在修改全域性變數時要先寫‘global 變數名‘,此時才可以修改;如果全域性變數是可變型別,則可以直接修改。

底層機制為:函式內修改全域性變數時,不可以更改全域性變數的記憶體地址路徑。呼叫的話是隨便的,不需要進行其他特殊操作。

for一顆栗子

from functools import wraps
tag = False  #不可變型別的全域性變數
def auth(name=None):
   def app(func):
       @wraps(func)
       def check(*args,**kwargs):
           global tag  #宣告全域性變數
           if tag == False:
               name = input(`your name:`).strip()
               pwd = input(`your password:`).strip()
               with open(`c.txt`,mode=`rt`,encoding=`utf-8`) as f:
                   dic = eval(f.read())  #eval可以理解為將內容原封不動的輸出,原來是字典,輸出還是字典
                   if name in dic and dic[name] == pwd:
                       print(`login successful`)
                       tag = True  #修改不可變型別的全域性變數,使後續函式不用再次認證
                       res=func(*args,**kwargs)
                       return res

                   else:
                       print(`error`)
           else:
               res = func(*args,**kwargs)
               return res
       return check
   return app

@auth()
def index():
   print(`from index`)


index()

@auth()
def home(name):
   print(`welcome %s to home` %name)

home(`egon`)




 

上下兩個例子分別使用了三層和兩層函式,注意兩者修飾器引用上的區別,還有全域性變數和函式內變數之間的關係(name)

from functools import wraps
tag = {`name`:None,`pwd`:False}  #字典是可變型別,修改字典時不會修改tag所對應的資料路徑
def app(func):
       @wraps(func)
       def check(*args,**kwargs):
           if tag[`name`] and tag[`pwd`]:
               res = func(*args,**kwargs)
               return res
           else:
               name = input(`your name:`).strip()
               pwd = input(`your password:`).strip()
               with open(`c.txt`,mode=`rt`,encoding=`utf-8`) as f:
                   dic = eval(f.read())  
                   if name in dic and dic[name] == pwd:
                       print(`login successful`)
                       tag[`name`]=True
                       tag[`pwd`]=True
                       res=func(*args,**kwargs)
                       return res

                   else:
                       print(`error`)
       return check

@app
def index():
   print(`from index`)


index()

@app
def home(name):
   print(`welcome %s to home` %name)

home(`egon`)

 

相關文章