中文字幕av专区_日韩电影在线播放_精品国产精品久久一区免费式_av在线免费观看网站

溫馨提示×

溫馨提示×

您好,登錄后才能下訂單哦!

密碼登錄×
登錄注冊×
其他方式登錄
點擊 登錄注冊 即表示同意《億速云用戶服務條款》

如何進行Python函數裝飾器的使用

發布時間:2022-01-15 15:41:28 來源:億速云 閱讀:127 作者:柒染 欄目:開發技術

如何進行Python函數裝飾器的使用,針對這個問題,這篇文章詳細介紹了相對應的分析和解答,希望可以幫助更多想解決這個問題的小伙伴找到更簡單易行的方法。

    裝飾器

    裝飾器的定義

    關于裝飾器的定義,我們先來看一段github上大佬的定義:

    Function decorators are simply wrappers to existing functions.
    In the context of design patterns,decorators dynamically alter the functionality of a function, method or class without having to directly use subclasses.
    This is ideal when you need to extend the functionality of functions that you don’t want to modify.
    We can implement the decorator pattern anywhere, but Python facilitates the implementation by providing much more expressive features and syntax for that.

    這段話的最主要的意思就是:

    函數裝飾器是給已有函數的簡單容器。
    在原有的代碼環境下,它能夠動態地改變一個函數的功能,或者不直接使用子類而改變方法和類。
    當你不想修改源代碼但又想實現功能上的擴充的時候,這是一個不錯的方法。
    我們可以在任何情況下使用裝飾器樣式,同時Python通過提供更多強力的屬性和語法來幫助裝飾器的使用。

    裝飾器的意義

    在上文之中其實我們已經知道了裝飾器的意義,
    可以不需要修改源代碼就能夠直接做到功能的擴充,但是為此我們需要付出的是更多的編寫時間,
    而且更為重要的是,通過修改源碼實現功能的增加往往會改變接口傳遞的參數,可一個項目之中往往存在許多接口這也代表著你可能需要多次更改接口參數,
    這個工作量,我們可不干!

    裝飾器的使用

    無參裝飾器

    無參裝飾器是最為基礎的裝飾器,
    其根本原因在于裝飾的函數對象不需要仍和的參數;
    接下來示范一下最簡單的裝飾器是如何實現的:

    def greeting():						# 定義一個最基本的無參函數
        return "Hello,讀者老爺們!"
    # 現在我需要實現的要求是:讓輸出的內容變為<p>"Hello,讀者老爺們"<p>
    # 在不直接更改greeting函數的前提下,我們需要使用無參裝飾器
    def decorator_p(func):				# 用于接收一個函數
    	def wrapper():
    		return f'<p>{func()}<p>'
    	return wrapper
    decorator = decorator_p(greeting)		# 調用decorator_p,并且用一個decorator接收返回值
    print(decorator())

    <p>Hello,讀者老爺們!<p>
    以上就是輸出的結果

    但是這個結果我其實并不滿意,
    因為完成了功能附加之后我們居然還需要再使用decorator = decorator_p(greeting)來接收一下,而且這樣的話調用方式就不再是原本的greeting()了,而是decorator()
    這兩者對于追求高效優雅的Python來說已經提供解決方法了,
    讓我娓娓道來:

    # 針對于調用方式而言,我們首先想到的解決方法是
    greeting = decorator_p(greeting)		# 將原本的greeting函數傳給decorator_p,而重命名
    print(greeting())						# 輸出結果與原來相同
    但這個仍然可以改進,這就要使用到Python提供的@,
    但使用這種方法必須注意書寫的順序,因此代碼必須這樣更改:
    def decorator_p(func):
        def wrapper():
            return f'<p>{func()}<p>'
        return wrapper
    
    @decorator_p					# 效果等同于 greeting = decorator_p(greeting)
    def greeting():
        return "Hello,讀者老爺們!"
    print(greeting())

    <p>Hello,讀者老爺們!<p>

    得到的結果是我們想要的,但使用這種方法順序格外重要,
    如果這樣書寫,則會給出報錯:

    @decorator_p						#使用這個@后,將會開始向上尋找decorator_p這個函數
    def greeting():
        return "Hello,讀者老爺們!"
    print(greeting())
    
    def decorator_p(func):
        def wrapper():
            return f'<p>{func()}<p>'
        return wrapper

    NameError: name &lsquo;decorator_p&rsquo; is not defined

    給出的報錯原因是因為沒有找到decorator_p這個函數,
    可明明我們已經完成這個函數的定義了,
    所以我們可以得到的結論便是:

    當使用@時,就會開始向上尋找函數,當找不到函數的時候就會報錯

    有參裝飾器

    接下來介紹一下有參裝飾器,就是指需要傳遞參數的裝飾器,
    上文之中其實已經介紹過了關于無參裝飾器的使用,而有參裝飾器也并沒有多難,
    來一個示范:

    def decorator(func):
        def wrapper(name):
            return f'<p>{func(name)}<p>' 
        return wrapper
    
    @decorator
    def greeting(name):
        return f"Hello,{name}!"
    print(greeting('讀者老爺'))		# 傳遞一個參數

    <p>Hello,讀者老爺!<p>

    實例練習

    OK,經過上文介紹所有讀者應該又會處于似懂非懂的狀態,
    那么秉持一文一練的理念,我們接下來將通過編寫登錄功能,仔細看一下使用裝飾器和不適用裝飾器的區別。
    在開始之前,我創建了一個文本文件夾,將會用于模擬用戶儲存的信息,內容如下:

    sign_in.txt
    Joseph:Jostar
    Jonasen:Jostar
    Kujo:Jotaro
    Jolin:Kujo
    Diavollo:Doppio

    需求清單:
    1)用戶賬戶只能夠由數字和英文組成,長度不超過16字符;
    2)用戶密碼只能夠由數字和英文組成,長度不超過16字符;
    3)用戶擁有4次輸入的機會。

    # 不使用任何函數
    # 無裝飾器 登錄功能
    count = 1				# 用于計算使用次數
    while count < 5:
        user_account = input('請輸入你的賬號')
        if user_account.isalnum() and len(user_account) <= 16:		# 判斷賬號長度和組成
            user_keyword = input('請輸入你的密碼')
            if user_keyword.isalnum() and len(user_keyword) <= 16:	# 判斷密碼的長度和組成
                with open('sign_in.txt','r') as file:				# 打開登錄文件核對登錄信息
                    for line in file:
                        r_name, r_keyword = line.strip().split(':')
                        if r_name == user_account and r_keyword == user_keyword:
                            print('登錄成功')
                            break
                    else:
                        count += 1
                        print(f'賬號密碼不匹配,還剩下{5-count}次機會')
                        continue
                    break
            else:
                count += 1
                print(f'密碼輸入錯誤,還剩下{5-count}次機會')
                continue
        else:
            count += 1
            print(f'輸入賬號錯誤,還剩下{5-count}次機會')
            continue
    else:
        print('機會已用完')

    程序員之間總是流傳著這么一個梗,
    開發總是會看著一串代碼愣愣出神說道:“這究竟是誰寫的代碼,像坨屎。”
    然后過了良久突然說“好像是我自己寫的。”

    接下來我們需要做的就是改良,使用裝飾器將其改良,
    我們的源代碼將其固定成這樣:

    # 只是單純的用戶輸入,
    # 而后我們要在此基礎上不斷優化,為其添加上判斷長度、限制次數的功能
    def input_signup():
        user_name = input('請輸入賬戶名字')
        user_keyword = input('請輸入賬戶密碼')
        return user_name, user_keyword
    def passing_func(func1, func2, func3):
        def wrapper(func4):
            def decorator():
                count = 1
                while count < 5:
                    name, keyword = func4()
                    check = func1(name, keyword)
                    if check is not True:
                        count += 1
                        print(f'你還剩下{5-count}次登錄機會')
                        continue
                    check = func2(name, keyword)
                    if check is not True:
                        count += 1
                        print(f'你還剩下{5-count}次登錄機會')
                        continue
                    check = func3(name, keyword)
                    if check is not True:
                        count += 1
                        print(f'你還剩下{5 - count}次登錄機會')
                        continue
                    else:
                        break
            return decorator
        return wrapper
    
    
    def limit_len(name, keyword, length=16):
        '''
        用于判斷用戶名字和密碼的長度是否符合標準
        :param   name:用于接受用戶的名字
        :param   keyword:用于接受用戶的密碼
        :param   length:默認參數為16
        :return: check:用于判斷輸入是否符合長度標準,詳細請見裝飾器中的使用
        '''
    
        check = True
        if len(name) > length or len(keyword) > length:
            print('賬號名或密碼長度不符合規范')
            check = False
            return check
        return check
    
    
    def limit_composition(name, keyword):
        '''
        用于判斷用戶名字和密碼的組成是否符合標準
        :param   name:用于接受用戶的名字
        :param   keyword:用于接受用戶的密碼
        :return: check:用于判斷輸入是否符合長度標準,詳細請見裝飾器中的使用
        '''
    
        check = True
        if name.isalnum() is not True or keyword.isalnum() is not True:
            print('賬號名或密碼組成不符合規范')
            check = False
            return check
        return check
    
    
    def verify_useinfo(name, keyword):
        '''
        用于檢驗用戶輸入的賬號和密碼是否符合文件中儲存的
        :param   name:用于接受用戶的名字
        :param   keyword:用于接受用戶的密碼
        :return: check:用于判斷輸入是否符合長度標準,詳細請見裝飾器中的使用
        '''
        check = True
        with open('sign_in.txt','r') as file:
            for line in file:
                r_name, r_keyword = line.strip().split(':')
                if r_name == name and r_keyword == keyword:
                    print('登錄成功,歡迎使用')
                    return check
            else:
                check = False
                print('賬號密碼錯誤,請重新輸入')
                return check
    
    
    @passing_func(limit_len, limit_composition, verify_useinfo)
    def input_signup():
        user_name = input('請輸入賬戶名字')
        user_keyword = input('請輸入賬戶密碼')
        return user_name, user_keyword

    關于如何進行Python函數裝飾器的使用問題的解答就分享到這里了,希望以上內容可以對大家有一定的幫助,如果你還有很多疑惑沒有解開,可以關注億速云行業資訊頻道了解更多相關知識。

    向AI問一下細節

    免責聲明:本站發布的內容(圖片、視頻和文字)以原創、轉載和分享為主,文章觀點不代表本網站立場,如果涉及侵權請聯系站長郵箱:is@yisu.com進行舉報,并提供相關證據,一經查實,將立刻刪除涉嫌侵權內容。

    AI

    保德县| 舞钢市| 政和县| 白水县| 湘阴县| 德清县| 元阳县| 江陵县| 仲巴县| 闽侯县| 潮州市| 体育| 邹平县| 正宁县| 临泉县| 合作市| 江西省| 广丰县| 长岛县| 株洲县| 沂南县| 云浮市| 通山县| 庆云县| 菏泽市| 呼玛县| 英吉沙县| 子洲县| 东兰县| 巨野县| 紫云| 扶沟县| 科技| 开封市| 永寿县| 政和县| 大埔区| 霍山县| 十堰市| 龙州县| 渭源县|