nonlocal關鍵字、裝飾器

nonlocal關鍵字

# 做用:將 L 與 E(E中的名字須要提早定義) 的名字統一

# 應用場景:若是想在被嵌套的函數中修改外部函數變量(名字)的值

# 案例:

def outer():
    num = 10
    print(num)  # 10 
    def inner():
        nonlocal num
        num = 20
        p77rint(num)  # 20
    inner()
    print(num)  # 20

開放封閉原則:不改變調用方式與源代碼上增長功能

'''
1.不能修改被裝飾對象(函數)的源代碼(封閉)
2.不能更改被修飾對象(函數)的調用方式,且能達到增長功能的效果(開放)
'''

裝飾器

# 把要被裝飾的函數做爲外層函數的參數經過閉包操做後返回一個替代版函數
# 被裝飾的函數:fn
# 外層函數:outer(func)  outer(fn) => func = fn
# 替代版函數: return inner: 原功能+新功能

def fn():
    print("原有功能")

# 裝飾器
def outer(tag):
    def inner():
        tag()
        print(新增功能")
    return inner
fn = outer(fn)              
              
fn()

@語法糖: @外層函數

def outer(f):
    def inner():
        f()
        print("新增功能1")
    return inner
              
def wrap(f):
    def inner():
        f()
        print("新增功能2")
    return inner              

@wrap  # 被裝飾的順序決定了新增功能的執行順序
@outer  # <==> fn = outer(fn): inner      
def fn():
    print("原有功能")

有參有返的函數被裝飾

def check_usr(fn):  # fn, login, inner:不一樣狀態下的login,因此參數是統一的
    def inner(usr, pwd):
        # 在原功能上添加新功能
        if not (len(usr) >= 3 and usr.isalpha()):
            print('帳號驗證失敗')
            return False
        
        # 原有功能
        result = fn(usr, pwd)
        
        # 在原功能下添加新功能
        # ...
        
        return result
       return inner


@check_usr
def login(usr, pwd):
    if usr == 'abc' and pwd =='123qwe':
        print('登陸成功')
        return True
    print('登陸失敗')
    return False

# 總結:
# 1.login有參數,因此inner與fn都有相同參數
# 2.login有返回值,因此inner與fn都有返回值

"""
inner(usr, pwd):
    res = fn(usr, pwd)  # 原login的返回值
    return res


login = check_usr(login) = inner

res = login('abc', '123qwe')  # inner的返回值
"""

裝飾器最終寫法

def wrap(fn):
    def inner(*args, **kwargs):
        print('前增功能')
        result = fn(*args, **kwargs)
        print('後增功能')
        return result
    return inner

@wrap
def fn1():
    print('fn1的原有功能')
@wrap
def fn2(a, b):
    print('fn2的原有功能')
@wrap   
def fn3():
    print('fn3的原有功能')
    return True
@wrap
def fn4(a, *, x):
    print('fn4的原有功能')
    return True

fn1()
fn2(10, 20)
fn3()
fn4(10, x=20)

帶參裝飾器:瞭解

# 瞭解
def outer(input_color):
    def wrap(fn):
        if input_color == 'red':
            info = '\033[36;41mnew action\33[0m'
        else:
            info = 'yellow:new action'

        def inner(*args, **kwargs):
            pass
            result = fn(*args, **kwargs)
            print(info)
            return result
        return inner
    return wrap  # outer(color) => wrap


color = input('color: ')
@outer(color)  # @outer(color) ==> @wrap  # func => inner
def func():
    print('func run')

func()

登陸認證功能

is_login = False  # 登陸狀態

def login():
    usr = input('usr: ')
    if not (len(usr) >= 3 and usr.isalpha()):
        print('帳號驗證失敗')
        return False
    pwd = input('pwd: ')
    if usr == 'abc' and pwd =='123qwe':
        print('登陸成功')
        is_login = True
    else:
        print('登陸失敗')
        is_login = False


# 完成一個登陸狀態校驗的裝飾器
def check_login(fn):
    def inner(*args, **kwargs):
        # 查看我的主頁或銷售功能前:若是沒有登陸先登陸,反之能夠進入其功能
        if is_login != True:
            print('你未登陸')
            login()
        # 查看我的主頁或銷售
        result = fn(*args, **kwargs)
        return result
    return inner

# 查看我的主頁功能
@check_login
def home():
    print('我的主頁')

# 銷售功能
@check_login
def sell():
    print('能夠銷售')

home()
相關文章
相關標籤/搜索