Heim  >  Artikel  >  Backend-Entwicklung  >  Python-Dekoratoren – Verschlüsse und Funktionsdekoratoren

Python-Dekoratoren – Verschlüsse und Funktionsdekoratoren

PHPz
PHPznach vorne
2023-04-10 14:51:071592Durchsuche

1. Abschlüsse

Bevor Sie Dekorateure lernen, müssen Sie das Konzept der Abschlüsse verstehen. Die wichtigsten Punkte beim Bilden eines Abschlusses:

  • Funktionsverschachtelung
  • Verwenden Sie die interne Funktion als Rückgabewert der externen Funktion
  • Die interne Funktion muss die Variablen der externen Funktion verwenden

Das Folgende ist ein Berechnungsfall der Durchschnitt einer Liste, um das Abschlusspaket zu erklären:

def make_average():
# 创建一个列表,用来保存数值
nums = []

# 定义一个内部函数,用来计算列表的平均值
def average(n):
# 将数值添加到列表中
nums.append(n)
# 返回平均值
return sum(nums) / len(nums)

return average
  1. Definieren Sie zunächst eine Funktion make_average.
  2. Zweitens definieren Sie eine leere Liste innerhalb der Funktion make_average, um Werte zu speichern
  3. Verwenden Sie schließlich diese innere Funktion als Rückgabewert der äußeren Funktion make_average. Das Hinzufügen von () wird zu einem Aufruf dieser Funktion.
  4. # 调用外部函数,并将其复制给一个变量,注意:此时返回的是内函数的内存地址
    a = make_average()
    # 给这个变量加(),就相当于调用了内函数average
    print(a(20))
    print(a(30))
  5. Die laufenden Ergebnisse sind wie folgt: Wenn der übergebene Wert 20 ist, gibt es nur eine Zahl in der Liste, also ist das Berechnungsergebnis 20; wenn ein weiterer Wert 30 übergeben wird, gibt es zwei Zahlen 20 und 30 in der Liste. Das berechnete Ergebnis des Durchschnitts beträgt also 25.

Python-Dekoratoren – Verschlüsse und Funktionsdekoratoren 2. Decorator-Einführung

Es gibt beispielsweise die folgenden zwei Funktionen, die die Summe und den Punktestand von zwei Zahlen berechnen bzw.:

def add(a, b):
"""计算两数之和"""
res = a + b
return res

def mul(a, b):
"""计算两数之积"""
res = a * b
return res

Jetzt gibt es eine Anforderung: Ich möchte „Berechnung starten…“ drucken, bevor die Berechnung jeder Funktion beginnt, und „Berechnung endet…“, nachdem die Berechnung beendet ist. Wir können diese Anforderung erfüllen, indem wir den Funktionscode direkt ändern. Dabei treten jedoch die folgenden Probleme auf:

Wenn zu viele Funktionen geändert werden müssen, zehn oder sogar hundert Funktionen, ist das unrealistisch.

Es ist nicht praktisch Für eine spätere Wartung möchte ich beispielsweise nicht „Berechnung starten ...“, sondern „Beginn ...“ drucken. Wäre es nicht notwendig, es erneut zu ändern? Verstößt gegen das Offen- und Geschlossen-Prinzip (OCP), das heißt, der Entwurf des Programms erfordert Offenheit. Erweitern Sie das Programm und schließen Sie die Änderung des Programms. Daher ist die obige Methode zum direkten Ändern des Funktionscodes nicht möglich. Wir hoffen, die Funktion erweitern zu können, ohne die ursprüngliche Funktion zu ändern. Beispiel:
    def new_add(a, b):
    print("开始计算...")
    r = add(a, b)
    print("计算结束...")
    return r
    
    
    print(new_add(22, 33))
  1. Das Ausführungsergebnis lautet wie folgt:
  2. Obwohl diese Art der Erstellung einer neuen Funktion die ursprüngliche Funktion nicht ändert, besteht ein sehr ernstes Problem:

kann die angegebene Funktion nur erweitern und nicht Beispielsweise kann die obige Add-Funktion nicht erweitert werden, die Mul-Funktion jedoch nicht. Wenn Sie die Mul-Funktion erweitern möchten, können Sie nur eine Erweiterungsfunktion erstellen Eine universelle Erweiterungsfunktion, die alle Funktionen umfassen kann. Diese Art von universeller Funktion, die den ursprünglichen Funktionscode nicht ändert, ist: Dekorator.

2. Funktionsdekorator

Ein Dekorator ist im Wesentlichen eine Python-Funktion oder -Klasse, die es anderen Funktionen oder Klassen ermöglicht, zusätzliche Funktionen hinzuzufügen, ohne dass Codeänderungen erforderlich sind, dh zusätzliche Funktionen zu vorhandenen Objekten hinzugefügt werden Der Dekorateur ist auch ein Funktions-/Klassenobjekt. Es wird häufig in Szenarien mit übergreifenden Anforderungen verwendet, z. B. Protokolleinfügung, Leistungstests, Transaktionsverarbeitung, Caching, Berechtigungsüberprüfung usw. Python-Dekoratoren – Verschlüsse und Funktionsdekoratoren

1) Die dekorierte Funktion benötigt keine Parameter

Zum Beispiel:

def wrapper_info(func):
def inner():
print("开始介绍...")
res = func()
print("介绍结束...")
return res

return inner

def introduce1():
print("我是周润发,我来自HONG KONG")

info = wrapper_info(introduce1)
info()

Das laufende Ergebnis ist wie folgt:

Es ist ersichtlich, dass ohne Änderung des ursprünglichen Funktionscodes einige zusätzliche Funktionen hinzugefügt werden Originalfunktion, func Es ist die zu dekorierende Funktion. Sie wird als Variable an die Dekorationsfunktion übergeben und kann universell für andere Funktionen verwendet werden. Aber das aktuelle Problem ist: Was passiert, wenn die dekorierte Funktion Parameter annimmt? Zum Beispiel:

def introduce2(name, age):
print(f"我叫{name}, 我今年{age}岁了")

2) Die dekorierte Funktion hat Parameter

Obwohl Name und Alter im Dekorator „wrapper_info“ übergeben werden können, ist es auch möglich, dass nicht jede dekorierte Funktion nur Namen, Alter oder Parameter eines bestimmten Typs übergibt in einem Wörterbuch, einer Liste, einem Tupel usw. Was soll ich also tun, wenn Typ und Anzahl der übergebenen Parameter nicht festgelegt sind?

Zu diesem Zeitpunkt müssen Sie Parameter variabler Länge verwenden: (*args, **kwargs)

def wrapper_info(func):
"""
用来对其他函数进行扩展,使其他函数可以在执行前做一些额外的动作
:param func: 要扩展的函数对象
:return:
"""
def inner(*args, **kwargs):
print("开始介绍...")
res = func(*args, **kwargs)
print("介绍结束...")
return res

return inner

Zum Beispiel: Python-Dekoratoren – Verschlüsse und Funktionsdekoratoren

def introduce3(name, age, city):
print(f"我叫{name}, 我今年{age}岁了, 我来自{city}")

Die laufenden Ergebnisse lauten wie folgt:

3)装饰器带参数

上述提到的是装饰器,一种是应用于被装饰的函数不带参数,一种是被装饰的函数带参数,那装饰器本身能否带参数呢?比如我定义一个变量,想通过传入不同的值来控制这个装饰器实现不同的功能。答案是肯定的,例如:

def use_log(level):
def decorator(func):
def inner(*args, **kwargs):
if level == "warn":
logging.warning("%s is running by warning" % func.__name__)
elif level == "info":
logging.warning("%s is running by info" % func.__name__)
else:
logging.warning("%s is running by other" % func.__name__)
return func(*args, **kwargs)

return inner

return decorator


def introduce4(name, age, city):
print(f"我叫{name}, 我今年{age}岁了, 我来自{city}")


info1 = use_log(introduce4('周星驰', 28, '香港'))
info1('info')
info2 = use_log(introduce4('周润发', 28, '香港'))
info2('warn')
info3 = use_log(introduce4('成龙', 28, '香港'))
info3('xxx')

运行结果如下:

Python-Dekoratoren – Verschlüsse und Funktionsdekoratoren

3.装饰器调用

方式一:以函数方式调用

info3 = wrapper_info(introduce3)
info3('刘德华', 28, '香港')

如果是装饰器函数带参数,则调用方式为:

info4 = use_log(introduce4('周星驰', 28, '香港'))
info4('info')

方式二:以语法糖方式调用

即在被装饰函数上方以@符号进行修饰

@wrapper_info
def introduce3(name, age, city):
print(f"我叫{name}, 我今年{age}岁了, 我来自{city}")

introduce3('刘德华', 28, '香港')

如果是装饰器函数带参数,例如上述的use_log,则需要在装饰器中传入参数:

@use_log('info')
def introduce4(name, age, city):
print(f"我叫{name}, 我今年{age}岁了, 我来自{city}")

小结

什么是装饰器?

在不改变原函数代码的情况下,给原函数增加了一些额外的功能,并且能够通用于其他函数,这样的函数就称作为装饰器。

装饰器的调用

可以通过传统调用函数的方式进行调用,也可以通过@装饰器的方式调用

装饰器的特点

  • 通过装饰器,可以在不修改原来函数的情况下对函数进行扩展
  • 一个函数可以同时指定多个装饰器

Das obige ist der detaillierte Inhalt vonPython-Dekoratoren – Verschlüsse und Funktionsdekoratoren. Für weitere Informationen folgen Sie bitte anderen verwandten Artikeln auf der PHP chinesischen Website!

Stellungnahme:
Dieser Artikel ist reproduziert unter:51cto.com. Bei Verstößen wenden Sie sich bitte an admin@php.cn löschen