Heim  >  Artikel  >  Backend-Entwicklung  >  Einführung in Python-Dekoratoren

Einführung in Python-Dekoratoren

巴扎黑
巴扎黑Original
2017-08-07 17:57:261324Durchsuche

Der Dekorator in Python ist eine Hürde für den Einstieg in Python. Er ist vorhanden, egal ob Sie ihn überwinden oder nicht. Das Konzept der Dekoratoren in Python verwirrt die Leute oft, deshalb werde ich heute die Dekoratoren in Python analysieren

1. Geltungsbereich

In Python ist der Geltungsbereich in zwei Typen unterteilt: globaler Geltungsbereich und lokaler Geltungsbereich.

Der globale Geltungsbereich ist der auf Dateiebene definierte Variablen- und Funktionsname. Der lokale Bereich liegt innerhalb der definierenden Funktion.

Bezüglich des Umfangs muss ich zwei Punkte verstehen: a. Auf lokal definierte Variablen kann nicht global zugegriffen werden. b Auf global definierte Variablen kann nicht zugegriffen werden, aber auf global definierte Variablen kann nicht zugegriffen werden (natürlich gibt es Methoden). geändert)

Schauen wir uns das folgende Beispiel an:


x = 1
def funx():
  x = 10
  print(x) # 打印出10

funx()
print(x) # 打印出1

Wenn die Variable x nicht lokal definiert ist, dann startet die Funktion bei die Inside-Out-Suche nach lokaler Referenz, aber die Änderung kann nur global durchgeführt werden; wenn die erforderliche Variable nicht lokal gefunden wird, wird sie extern durchsucht und ein Fehler wird gemeldet, wenn sie nicht gefunden wird.


2. Erweiterte Funktionen

x = 1
def funx():
  print(x) # 打印出1

funx()
print(x) # 打印出1

x = 1
def funx():
  def func1():
    print(x) # 打印出1
  func1()

funx()
print(x) # 打印出1

Wir wissen, dass der Funktionsname tatsächlich auf die Adresse eines Speicherplatzes verweist. Da es sich um eine Adresse handelt, können wir diese Funktion verwenden.

ein Funktionsname kann als Wert verwendet werden

b. Funktionsname kann als Rückgabewert verwendet werden


def delete(ps):
  import os
  filename = ps[-1]
  delelemetns = ps[1]
  with open(filename, encoding='utf-8') as f_read,\
    open('tmp.txt', 'w', encoding='utf-8') as f_write:
    for line in iter(f_read.readline, ''):
      if line != '\n': # 处理非空行
        if delelemetns in line:
          line = line.replace(delelemetns,'')
        f_write.write(line)
  os.remove(filename)
  os.rename('tmp.txt',filename)

def add(ps):
  filename = ps[-1]
  addelemetns = ps[1]
  with open(filename, 'a', encoding='utf-8') as fp:
    fp.write("\n", addelemetns)

def modify(ps):
  import os
  filename = ps[-1]
  modify_elemetns = ps[1]
  with open(filename, encoding='utf-8') as f_read, \
      open('tmp.txt', 'w', encoding='utf-8') as f_write:
    for line in iter(f_read.readline, ''):
      if line != '\n': # 处理非空行
        if modify_elemetns in line:
          line = line.replace(modify_elemetns, '')
        f_write.write(line)
  os.remove(filename)
  os.rename('tmp.txt', filename)


def search(cmd):
  filename = cmd[-1]
  pattern = cmd[1]
  with open(filename, 'r', encoding="utf-8") as f:
    for line in f:
      if pattern in line:
        print(line, end="")
    else:
      print("没有找到")

dic_func ={'delete': delete, 'add': add, 'modify': modify, 'search': search}

while True:
  inp = input("请输入您要进行的操作:").strip()
  if not inp:
    continue
  cmd_1 = inp.split()
  cmd = cmd_1[0]
  if cmd in dic_func:
    dic_func[cmd](cmd_1)
  else:
    print("Error")

c.. Der Funktionsname kann als Parameter verwendet werden


def outer():
  def inner():
    pass
  return inner

s = outer()
print(s)

######输出结果为#######
<function outer.<locals>.inner at 0x000000D22D8AB8C8>

Daher, wenn einer der beiden oben genannten Wenn die Bedingungen erfüllt sind, kann sie als erweiterte Funktion bezeichnet werden.


3. Abschlussfunktion

def index():
  print("index func")

def outer(index):
  s = index
  s()
  
outer(index)

######输出结果#########

index func

Die Abschlussfunktion muss zwei Bedingungen erfüllen: 1. Funktion innerhalb der Funktion definiert 2. Enthält einen externen Bereich anstelle eines globalen Bereichs. Bereichsreferenz

Das Folgende veranschaulicht die Abschlussfunktion anhand einiger Beispiele: Beispiel 1: Im Folgenden wird nur eine Funktion innerhalb der Funktion definiert, es handelt sich jedoch nicht um einen Abschluss Funktion.

Beispiel 2: Das Folgende definiert eine Funktion innerhalb der Funktion und verweist auch auf eine externe Variable x. Antwort: Nein


def outer():
  def inner():
    print("inner func excuted")
  inner() # 调用执行inner()函数
  print("outer func excuted")
outer() # 调用执行outer函数

####输出结果为##########
inner func excuted
outer func excuted

Wenn Sie auf die Definition der Verschlussfunktion zurückblicken, stellt sich die Frage, ob sie beide erfüllt. Wenn Sie schlau sind, müssen Sie feststellen, dass die zweite Funktion nicht erfüllt ist. Ja, die Variable x hier ist eine globale Variable, keine Variable, die extern auf die Domäne wirkt. Schauen wir uns das folgende Beispiel an:


x = 1
def outer():
  def inner():
    print("x=%s" %x) # 引用了一个非inner函数内部的变量
    print("inner func excuted")
  inner() # 执行inner函数
  print("outer func excuted")

outer()
#####输出结果########
x=1
inner func excuted
outer func excuted

Offensichtlich erfüllt das obige Beispiel die Bedingungen der Abschlussfunktion. Nun sollten Sie wissen, dass sie als Abschlussfunktion die beiden oben genannten Bedingungen erfüllen muss, von denen eine unabdingbar ist. Unter normalen Umständen geben wir jedoch einen Wert an die Abschlussfunktion zurück. Im folgenden Inhalt sehen Sie die Verwendung dieses Rückgabewerts

Nun definieren wir die Abschlussfunktion abstrakt. Es handelt sich um eine Einheit, die aus einer Funktion und der zugehörigen Referenzumgebung besteht. Wenn Sie tiefe Einschränkungen implementieren, müssen Sie etwas erstellen, das die Referenzumgebung explizit darstellt, und es mit der entsprechenden Unterroutine bündeln, sodass das Bündel zu einem Abschluss wird. Im obigen Beispiel können wir feststellen, dass die Abschlussfunktion eine eigene Funktion und eine externe Variable enthalten muss, um wirklich als Abschlussfunktion bezeichnet zu werden. Wenn keine externe Variable daran gebunden ist, kann die Funktion nicht als Abschlussfunktion betrachtet werden.

Woher wissen Sie also, wie viele externe Referenzvariablen eine Abschlussfunktion hat?
def outer():
  x = 1
  def inner():
    print("x=%s" %x)
    print("inner func excuted")
  inner()
  print("outer func excuted")

outer()

#####输出结果#########
x=1
inner func excuted
outer func excuted


Die Ergebnisse zeigen das im Inneren die innere , die auf zwei externe lokale Variablen verweist. Wenn auf eine nicht lokale Variable verwiesen wird, lautet die Ausgabe hier „Keine“.
def outer():
  x = 1
  def inner():
    print("x=%s" %x)
    print("inner func excuted")
  print("outer func excuted")
  return inner # 返回内部函数名
  
outer()

Merkmale der Abschlussfunktion:

1 Kommt mit Gültigkeitsbereich 2. Verzögerte Berechnung

Dann Abschluss Was macht die Paketfunktion? Wir wissen eindeutig, dass die Abschlussfunktion bei der Definition an eine externe Umgebung gebunden wird. Das Ganze kann als Abschlussfunktion betrachtet werden. Dann können wir diese Bindungsfunktion verwenden, um bestimmte Sonderfunktionen auszuführen.

Beispiel 3: Laden Sie den Seitenquellcode basierend auf der eingehenden URL herunter
def outer():
  x = 1
  y = 2

  def inner():
    print("x= %s" %x)
    print("y= %s" %y)

  print(inner.__closure__)
  return inner

outer()

######输出结果#######
(<cell at 0x000000DF9EA965B8: int object at 0x000000006FC2B440>, <cell at 0x000000DF9EA965E8: int object at 0x000000006FC2B460>)

Einige Leute sagen möglicherweise, dass dies nicht den Bedingungen der entspricht Abschlussfunktion Ah! Ich habe nicht auf nicht-globale externe Variablen verwiesen. Tatsächlich ist dies nicht der Fall, solange die Variablen innerhalb der Funktion zur Funktion gehören. Dann bin ich bei index(url), diese URL gehört auch in die Funktion, aber wir haben einen Schritt ausgelassen, sodass die obige Funktion auch eine Abschlussfunktion ist.

4. Dekorator

Mit der oben genannten Grundlage ist der Dekorator leicht zu verstehen: Die übergebene externe Funktion ist dekorierte Funktion Name, die interne Funktion gibt den dekorierten Funktionsnamen zurück.

Eigenschaften: 1. Ändert nicht die Aufrufmethode der dekorierten Funktion. 2. Ändert nicht den Quellcode der dekorierten Funktion.
from urllib.request import urlopen

def index(url)
  def get()
    return urlopen(url).read()
  return get

python = index("http://www.python.org") # 返回的是get函数的地址
print(python()) # 执行get函数《并且将返回的结果打印出来
baidu = index("http://www.baidu.com")
print(baidu())

a. Kein Argument-Dekorator

Es gibt die folgenden Beispiele: Wir müssen die Ausführungszeit des Codes berechnen.

import time, random

def index():
  time.sleep(random.randrange(1, 5))
  print("welcome to index page")

  根据装饰器的特点,我们不能对index()进行任何修改,而且调用方式也不能变。这时候,我们就可以使用装饰器来完成如上功能.


import time, random

def outer(func): # 将index的地址传递给func
  def inner():
    start_time = time.time()
    func()  # fun = index 即func保存了外部index函数的地址
    end_time = time.time()
    print("运行时间为%s"%(end_time - start_time))
  return inner # 返回inner的地址

def index():
  time.sleep(random.randrange(1, 5))
  print("welcome to index page")

index = outer(index) # 这里返回的是inner的地址,并重新赋值给index

index()

  但是,有些情况,被装饰的函数需要传递参数进去,有些函数又不需要参数,那么如何来处理这种变参数函数呢?下面来看看有参数装饰器的使用情况.

  b.有参装饰器


def outer(func): # 将index的地址传递给func
  def inner(*args, **kwargs):
    start_time = time.time()
    func(*args, **kwargs)  # fun = index 即func保存了外部index函数的地址
    end_time = time.time()
    print("运行时间为%s"%(end_time - start_time))
  return inner # 返回inner的地址

  下面来说说一些其他情况的实例。

   如果被装饰的函数有返回值


def timmer(func):
  def wrapper(*args,**kwargs):
    start_time = time.time()
    res=func(*args,**kwargs) #res来接收home函数的返回值
    stop_time=time.time()
    print(&#39;run time is %s&#39; %(stop_time-start_time))
    return res 
  return wrapper

def home(name):
  time.sleep(random.randrange(1,3))
  print(&#39;welecome to %s HOME page&#39; %name)
  return 123123123123123123123123123123123123123123

  这里补充一点,加入我们要执行被装饰后的函数,那么应该是如下调用方式:

  home = timmer(home)  # 等式右边返回的是wrapper的内存地址,再将其赋值给home,这里的home不在是原来的的那个函数,而是被装饰以后的函数了。像home = timmer(home)这样的写法,python给我们提供了一个便捷的方式------语法糖@.以后我们再要在被装饰的函数之前写上@timmer,它的效果就和home = timmer(home)是一样的。

  如果一个函数被多个装饰器装饰,那么执行顺序是怎样的。


import time
import random

def timmer(func):
  def wrapper():
    start_time = time.time()
    func()
    stop_time=time.time()
    print(&#39;run time is %s&#39; %(stop_time-start_time))
  return wrapper
def auth(func):
  def deco():
    name=input(&#39;name: &#39;)
    password=input(&#39;password: &#39;)
    if name == &#39;egon&#39; and password == &#39;123&#39;:
      print(&#39;login successful&#39;)
      func() #wrapper()
    else:
      print(&#39;login err&#39;)
  return deco

@auth  # index = auth(timmer(index))         
@timmer # index = timmer(index)
def index():
 
  time.sleep(3)
  print(&#39;welecome to index page&#39;)

index()

  实验结果表明,多个装饰器装饰一个函数,其执行顺序是从下往上。

  关于装饰器,还有一些高级用法,有兴趣的可以自己研究研究。

Das obige ist der detaillierte Inhalt vonEinführung in Python-Dekoratoren. Für weitere Informationen folgen Sie bitte anderen verwandten Artikeln auf der PHP chinesischen Website!

Stellungnahme:
Der Inhalt dieses Artikels wird freiwillig von Internetnutzern beigesteuert und das Urheberrecht liegt beim ursprünglichen Autor. Diese Website übernimmt keine entsprechende rechtliche Verantwortung. Wenn Sie Inhalte finden, bei denen der Verdacht eines Plagiats oder einer Rechtsverletzung besteht, wenden Sie sich bitte an admin@php.cn