国产片侵犯亲女视频播放_亚洲精品二区_在线免费国产视频_欧美精品一区二区三区在线_少妇久久久_在线观看av不卡

腳本之家,腳本語言編程技術及教程分享平臺!
分類導航

Python|VBS|Ruby|Lua|perl|VBA|Golang|PowerShell|Erlang|autoit|Dos|bat|

服務器之家 - 腳本之家 - Python - Python函數裝飾器指南

Python函數裝飾器指南

2020-10-17 23:23Yujiaao Python

Python 具有強大的功能和富有表現力的語法。我最喜歡的裝飾之一。本文為大家介紹下Python函數裝飾器的使用方法,有需要的朋友可以參考下

Python 具有強大的功能和富有表現力的語法。我最喜歡的裝飾之一。在設計模式的上下文中,裝飾器動態更改方法或類功能,而不必直接使用子類。當您需要擴展功能,但不想修改原函數時,這是理想的選擇。我們可以在任何地方實現裝飾器模式,但是 Python 通過提供更具表現力的功能和語法來促進實現。

在這篇文章中,將討論 Python 的函數裝飾器,并附帶一些澄清有關概念的示例。所有示例均適用 Python 2.7,但相同的概念應適用于Python 3,但語法有所更改。

本質上,裝飾器充當包裝器,在目標函數執行之前和之后修改代碼的行為,而無需修改函數本身,從而增強了原始功能,從而對其進行了裝飾。

您需要了解的功能

 

在潛水之前,應先弄清一些先決條件。在 Python 中,函數是一等公民,它們是對象,這意味著我們可以用它們做很多有用的事情。

將函數分配給變量

1
2
3
4
5
6
7
def greet(name):
    return "hello "+name
 
greet_someone = greet
print(greet_someone("John"))
 
# 輸出: hello John

在其他函數中定義函數

1
2
3
4
5
6
7
8
9
10
def greet(name):
    def get_message():
        return "Hello "
 
    result = get_message()+name
    return result
 
print(greet("John"))
 
# 輸出: Hello John

可以將函數作為參數傳遞給其他函數

1
2
3
4
5
6
7
8
9
10
def greet(name):
   return "Hello " + name
 
def call_func(func):
    other_name = "John"
    return func(other_name) 
 
print(call_func(greet))
 
# 輸出: Hello John

函數可以返回其他函數

換句話說, 函數生成其他函數。

1
2
3
4
5
6
7
8
9
10
def compose_greet_func():
    def get_message():
        return "Hello there!"
 
    return get_message
 
greet = compose_greet_func()
print(greet())
 
# 輸出: Hello there!

內部函數可以訪問封閉范圍

更通常稱為閉包。在構建裝飾器時會遇到的一種非常強大的模式。還要注意的另一件事是,Python 只允許對外部作用域進行讀取訪問,而不是賦值。請注意,我們如何修改上面的示例以從內部函數的封閉范圍中讀取“name” 參數并返回新函數。

1
2
3
4
5
6
7
8
9
10
def compose_greet_func(name):
    def get_message():
        return "Hello there "+name+"!"
 
    return get_message
 
greet = compose_greet_func("John")
print(greet())
 
# 輸出: Hello there John!

裝飾者的組成

 

函數裝飾器只是現有函數的包裝器。綜上所述,我們可以構建一個裝飾器。在此示例中,我們考慮一個函數,該函數通過p標簽包裝另一個函數的字符串輸出。

1
2
3
4
5
6
7
8
9
10
11
12
13
def get_text(name):
   return "lorem ipsum, {0} dolor sit amet".format(name)
 
def p_decorate(func):
   def func_wrapper(name):
       return "<p>{0}</p>".format(func(name))
   return func_wrapper
 
my_get_text = p_decorate(get_text)
 
print(my_get_text("John"))
 
# 輸出: <p> lorem ipsum, John dolor sit amet</p>

那是我們的第一個裝飾。一個將另一個函數作為參數的函數,將生成一個新函數,以擴展原始函數的功能,并返回生成的函數,以便我們可以在任何地方使用它。要讓 get_text 本身由 p_decorate 裝飾,我們只需將 p_decorate 的結果再賦值給 get_text 即可。

1
2
3
4
5
get_text = p_decorate(get_text)
 
print(get_text("John"))
 
# 輸出:<p>lorem ipsum, John dolor sit amet</p>

還要注意的另一點是,我們的修飾函數帶有一個 name 參數。在裝飾器中我們要做的就是讓 get_text 的包裝傳遞該參數。

Python的裝飾語法

 

Python通過一些語法糖使創建和使用裝飾器對程序員來說更干凈,更友好。不必裝飾 get_text,get_text = p_decorator(get_text) 它有一個捷徑,即在要使用的函數之前提供裝飾函數的名稱即可。裝飾器的名稱應帶有@符號。

1
2
3
4
5
6
7
8
9
10
11
12
def p_decorate(func):
   def func_wrapper(name):
       return "<p>{0}</p>".format(func(name))
   return func_wrapper
 
@p_decorate
def get_text(name):
   return "lorem ipsum, {0} dolor sit amet".format(name)
 
print(get_text("John"))
 
# 輸出: <p>lorem ipsum, John dolor sit amet</p>

現在,讓我們考慮我們要用其他2個函數來修飾 get_text 函數,以便在字符串輸出周圍包裝div和strong標簽。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
def p_decorate(func):
   def func_wrapper(name):
       return "<p>{0}</p>".format(func(name))
   return func_wrapper
 
def strong_decorate(func):
    def func_wrapper(name):
        return "<strong>{0}</strong>".format(func(name))
    return func_wrapper
 
def div_decorate(func):
    def func_wrapper(name):
        return "<div>{0}</div>".format(func(name))
    return func_wrapper

使用基本方法,裝飾 get_text 將遵循以下步驟:

1
get_text = div_decorate(p_decorate(strong_decorate(get_text)))

使用 Python 的裝飾器語法,可以用更具表達力的功能實現相同功能。

1
2
3
4
5
6
7
8
9
@div_decorate
@p_decorate
@strong_decorate
def get_text(name):
   return "lorem ipsum, {0} dolor sit amet".format(name)
 
print(get_text("John"))
 
# 輸出: <div><p><strong>lorem ipsum, John dolor sit amet</strong></p></div>

這里要注意的一件事是設置裝飾器的順序很重要。如果以上示例中的順序不同,則輸出將不同。

裝飾方式

 

在 Python 中,方法是期望其第一個參數成為對當前對象的引用的函數。我們可以以相同的方式為方法構建裝飾器,同時在包裝函數中考慮自身

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
def p_decorate(func):
   def func_wrapper(self):
       return "<p>{0}</p>".format(func(self))
   return func_wrapper
 
class Person(object):
    def __init__(self):
        self.name = "John"
        self.family = "Doe"
 
    @p_decorate
    def get_fullname(self):
        return self.name+" "+self.family
 
my_person = Person()
print(my_person.get_fullname())

更好的方法是使裝飾器對函數和方法都有用。這可以通過將*args 和 **kwargs作為包裝器的參數來完成,然后它可以接受任意數量的參數和關鍵字參數。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
def p_decorate(func):
   def func_wrapper(*args, **kwargs):
       return "<p>{0}</p>".format(func(*args, **kwargs))
   return func_wrapper
 
class Person(object):
    def __init__(self):
        self.name = "John"
        self.family = "Doe"
 
    @p_decorate
    def get_fullname(self):
        return self.name+" "+self.family
 
my_person = Person()
 
print(my_person.get_fullname())

將參數傳遞給裝飾器

 

回顧上面的示例之前的示例,您會注意到示例中的裝飾器是多么冗余。3個裝飾器(div_decorate,p_decorate,strong_decorate)具有相同的功能,但用不同的標簽包裝字符串。我們絕對可以做得更好。為什么不為將標簽包裝為字符串的標簽提供更通用的實現?是的,請!

1
2
3
4
5
6
7
8
9
10
11
12
13
14
def tags(tag_name):
    def tags_decorator(func):
        def func_wrapper(name):
            return "<{0}>{1}</{0}>".format(tag_name, func(name))
        return func_wrapper
    return tags_decorator
 
@tags("p")
def get_text(name):
    return "Hello "+name
 
print(get_text("John"))
 
# 輸出 <p>Hello John</p>

在這種情況下,需要做更多的工作。裝飾器期望接收一個函數作為參數,這就是為什么我們必須構建一個接受這些額外參數并動態生成裝飾器的原因。在上面的示例tags,是我們的裝飾器生成器。

調試裝飾功能

 

歸根結底,裝飾器只是包裝我們的函數,以防調試出現問題,因為包裝器函數不攜帶原始函數的名稱,模塊和文檔字符串。基于上面的示例,如果我們這樣做:

1
2
print(get_text.__name__)
# 輸出 func_wrapper

期待輸出get_text,然而,get_text__name____doc____module__屬性被包裝(func_wrapper)覆蓋。顯然,我們可以在func_wrapper中重置它們,但是Python提供了一種更好的方法。

救援工具

幸運的是,Python(從版本2.5開始)包括functools模塊,其中包含functools.wraps。Wraps 是一個修飾器,用于將包裝函數(func_wrapper)的屬性更新為原始函數(get_text)的屬性。這就像通過@wraps(func)裝飾func_wrapper一樣簡單。這是更新的示例:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
from functools import wraps
 
def tags(tag_name):
    def tags_decorator(func):
        @wraps(func)
        def func_wrapper(name):
            return "<{0}>{1}</{0}>".format(tag_name, func(name))
        return func_wrapper
    return tags_decorator
 
@tags("p")
def get_text(name):
    """returns some text"""
    return "Hello "+name
 
print(get_text.__name__) # get_text
print(get_text.__doc__) # returns some text
print(get_text.__module__) # __main__

您可以從輸出中注意到,get_text 的屬性現在是正確的屬性。

裝飾器在哪里使用

 

相對于您可以使用裝飾器完成的工作量,本文中的示例非常簡單。它們可以為您的程序提供如此強大的功能。通常,裝飾器是擴展我們不想修改的函數的行為的理想選擇。有關有用的裝飾器的大量清單,建議您查看Python Decorator Library

延伸 · 閱讀

精彩推薦
主站蜘蛛池模板: 日韩欧美在线一区 | 中文字幕在线一区 | 国产精品亚洲综合 | 希岛爱理av一区二区三区 | 99视频网站| 国产午夜一区二区三区 | 亚洲视频在线观看 | 台湾av片| 精品亚洲免费 | 国产综合久久 | 操av在线| 亚洲国产精品yw在线观看 | 日本免费高清视频 | 亚洲成人免费 | 干片网| 免费看国产片在线观看 | 日韩在线影院 | 黄色片在线免费观看 | 亚洲免费一区 | 午夜私人影院在线观看 | 都市激情综合 | 国产噜噜噜噜噜久久久久久久久 | 亚洲欧美视频在线观看 | 国产综合久久 | 成人网在线观看 | 亚洲美女一区 | 春色网站| 精品国产一级毛片 | 国产精品久久久久久婷婷天堂 | 日本高清无卡码一区二区久久 | 中国毛片基地 | 日日干夜夜干 | 国产成人在线视频 | 人体一区 | 欧美在线免费观看 | 欧美精品偷拍 | av在线播放网址 | 久久久极品| 久久精品视频免费 | 久久国内 | 国产精品国产三级国产aⅴ中文 |