我已經爲Flask用戶權限系統編寫了一個修飾器函數。當我嘗試點擊裝飾的視圖時,user
參數上的UnboundLocalError
。這裏的裝飾功能:修飾器中參數的範圍不一致
def user_is(role, user=None):
"""
Takes an role (a string name of either a role or an ability) and returns the function if the user has that role
"""
def wrapper(func):
@wraps(func)
def inner(*args, **kwargs):
from .models import Role
desired_role = Role.query.filter_by(
name=role).first()
if not user:
try:
from flast.ext.login import current_user as user
except ImportError:
raise ImportError(
'User argument not passed and Flask-Login current_user could not be imported.')
if desired_role in user.roles:
return func(*args, **kwargs)
else:
# Make this do someting way better.
return "You do not have access"
return inner
return wrapper
回溯表明user
是未定義if not user:
。我不確定這是怎麼回事。我的理解是,如果user
不存在於內部函數的作用域中,那麼Python將通過嵌套函數逐層出去,直到找到它爲止。這意味着我只應得到UnboundLocalError
如果user
是未定義在函數中,所有函數包裝它,並全局。這顯然不是這種情況。
另一個混亂的原因是,我能夠看到使用Werkzeug調試控制檯,我的其他參數是定義在此範圍內。如何定義一個參數,並將由裝飾器函數引入的另一個參數在程序流中的同一點處未定義?我想也許這是一個隻影響參數默認值的怪癖,所以我將它切換到一個必需的參數,並手動通過None
,但這仍然產生了錯誤?
當其他參數在範圍內時,爲什麼user
超出範圍?我怎樣才能修復這個裝飾器?
這很有道理。一個後續問題可以幫助我理解:在執行導入之前引發異常時,導入如何影響'user'的範圍? – raddevon
編譯器枚舉函數中的所有賦值;分配給(其中包括導入)的任何內容都會自動標記爲本地。其他一切都是一個自由變量。如果一個父範圍有一個匹配的本地,則從閉包中查找自由變量,否則它們是全局變量。你可以使用'global'關鍵字來覆蓋它(把本地標記爲全局變量),Python 3也增加了'nonlocal'關鍵字。 *其中*進口或轉讓發生無關緊要。在賦值或導入之前對名稱的任何引用都會引發'UnboundLocal'異常。 –