Maison développement back-end Tutoriel Python Exemple de partage de code qui vous permet d'avoir une compréhension approfondie des décorateurs Python

Exemple de partage de code qui vous permet d'avoir une compréhension approfondie des décorateurs Python

Jun 18, 2017 am 11:33 AM
python 了解 Peut aller en profondeur

Le décorateur en Python est un obstacle pour entrer en Python. Il est là, que vous le franchissiez ou non. Le concept de décorateurs en Python confond souvent les gens, je vais donc aujourd'hui analyser les décorateurs en Python

1. Portée

En python, la portée est divisée en deux types : portée mondiale et portée locale.

La portée globale est la variable et le nom de la fonction définis au niveau du fichier. La portée locale se trouve à l'intérieur de la fonction définie .

Concernant la portée, je dois comprendre deux points : a. Les variables définies localement ne sont pas accessibles globalement. b Les variables définies globalement sont accessibles localement, mais les variables définies globalement ne peuvent pas être modifiées (bien sûr, il existe des méthodes qui peuvent être utilisées). modifié)

Regardons l'exemple suivant :


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

funx()
print(x) # 打印出1
Copier après la connexion

S'il n'y a pas de variable définie x localement, alors la fonction En interne, elle recherchera x de l'intérieur vers l'extérieur. S'il n'est pas trouvé, une erreur sera signalée. Les variables globales peuvent être référencées n'importe où dans le fichier, mais les modifications ne peuvent être effectuées globalement que si la variable requise l'est. introuvable localement, il sera recherché en externe et une erreur sera signalée s'il n'est pas trouvé.


2. Fonctions avancées

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
Copier après la connexion

Nous savons que le nom de la fonction pointe en fait vers l'adresse d'un espace mémoire, puisqu'il s'agit d'une adresse, nous pouvons utiliser cette fonctionnalité.

un nom de fonction peut être utilisé comme valeur

b.


c.. Le nom de la fonction peut être utilisé comme paramètre
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")
Copier après la connexion


Par conséquent, si l'un des deux ci-dessus conditions est remplie, on peut l'appeler une fonction avancée.
def outer():
  def inner():
    pass
  return inner

s = outer()
print(s)

######输出结果为#######
<function outer.<locals>.inner at 0x000000D22D8AB8C8>
Copier après la connexion

3. Fonction de fermeture


La fonction de fermeture doit remplir deux conditions : 1. Fonction définie à l'intérieur de la fonction 2. Contient une portée externe plutôt qu'une portée globale Référence de portée
def index():
  print("index func")

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

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

index func
Copier après la connexion

Ce qui suit illustre la fonction de fermeture à travers quelques exemples :

Exemple 1 : Ce qui suit définit uniquement une fonction à l'intérieur de la fonction, mais ce n'est pas une fermeture function.

Exemple 2 : Ce qui suit définit une fonction à l'intérieur de la fonction et fait également référence à une variable externe x. Est-ce donc une fonction de fermeture ? 🎜>


En repensant à la définition de la fonction de fermeture, est-ce qu'elle satisfait les deux ? Si vous êtes intelligent, vous devez constater que la seconde n'est pas satisfaite. Oui, la variable x ici est une variable globale, pas une variable qui agit de l'extérieur sur le domaine. Regardons l'exemple suivant :

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

####输出结果为##########
inner func excuted
outer func excuted
Copier après la connexion


Évidemment, l'exemple ci-dessus satisfait aux conditions de la fonction de fermeture. Or, sachez qu’en tant que fonction de fermeture, il doit remplir les deux conditions ci-dessus, dont l’une est indispensable. Cependant, dans des circonstances normales, nous renverrons une valeur à la fonction de fermeture. Ne parlons pas de pourquoi ici. Dans le contenu suivant, vous verrez l'utilisation de cette valeur de retour

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
Copier après la connexion

.


Définissons maintenant la fonction de fermeture de manière abstraite. C'est une entité composée d'une fonction et de son environnement de référence associé. Lors de l'implémentation de contraintes profondes, vous devez créer quelque chose qui représente explicitement l'environnement de référence et le regrouper avec le sous-programme approprié, afin que le bundle devienne une fermeture. Dans l'exemple ci-dessus, nous pouvons constater que la fonction de fermeture doit contenir sa propre fonction et une variable externe pour être véritablement appelée fonction de fermeture. Si aucune variable externe n’y est liée, alors la fonction ne peut pas être considérée comme une fonction de fermeture.

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
Copier après la connexion
Alors, comment savoir combien de variables de référence externes possède une fonction de fermeture ? Regardez le code suivant


def outer():
  x = 1
  def inner():
    print("x=%s" %x)
    print("inner func excuted")
  print("outer func excuted")
  return inner # 返回内部函数名
  
outer()
Copier après la connexion
Les résultats montrent cela à l'intérieur. le inner , faisant référence à deux variables locales externes. Si une variable non locale est référencée, alors la sortie ici est Aucune.

Caractéristiques de la fonction de fermeture :

1 Livré avec la portée 2. Calcul retardé


Puis fermeture. Que fait la fonction package ? Nous savons clairement que lorsque la fonction de fermeture est définie, elle sera liée à un environnement externe. Tout cela peut être considéré comme une fonction de fermeture, nous pouvons alors utiliser cette fonction de liaison pour compléter certaines fonctions spéciales.

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>)
Copier après la connexion
Exemple 3 : Téléchargez le code source de la page en fonction de l'URL entrante

Certaines personnes peuvent dire que cela ne remplit pas les conditions du fonction de fermeture Ah ! je n'ai pas fait référence à une variable externe non globale. En fait, ce n'est pas le cas, comme nous l'avons dit précédemment, tant que les variables à l'intérieur de la fonction appartiennent à la fonction. Ensuite, je suis à index(url), cette URL appartient également à l'intérieur de la fonction, mais nous avons omis une étape, donc la fonction ci-dessus est également une fonction de fermeture.

4. Décorateur


Avec la base ci-dessus, il est facile de comprendre le décorateur

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())
Copier après la connexion
Décorateur : La fonction externe transmise est la fonction décorée. name, la fonction interne renvoie le nom de la fonction décorée.

Caractéristiques : 1. Ne modifie pas la méthode d'appel de la fonction décorée 2. Ne modifie pas le code source de la fonction décorée

a. Décorateur sans argument

Il existe les exemples suivants : nous devons calculer le temps d'exécution du code.


import time, random

def index():
  time.sleep(random.randrange(1, 5))
  print("welcome to index page")
Copier après la connexion

  根据装饰器的特点,我们不能对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()
Copier après la connexion

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

  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的地址
Copier après la connexion

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

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


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
Copier après la connexion

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

  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()
Copier après la connexion

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

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

Ce qui précède est le contenu détaillé de. pour plus d'informations, suivez d'autres articles connexes sur le site Web de PHP en chinois!

Déclaration de ce site Web
Le contenu de cet article est volontairement contribué par les internautes et les droits d'auteur appartiennent à l'auteur original. Ce site n'assume aucune responsabilité légale correspondante. Si vous trouvez un contenu suspecté de plagiat ou de contrefaçon, veuillez contacter admin@php.cn

Outils d'IA chauds

Undresser.AI Undress

Undresser.AI Undress

Application basée sur l'IA pour créer des photos de nu réalistes

AI Clothes Remover

AI Clothes Remover

Outil d'IA en ligne pour supprimer les vêtements des photos.

Undress AI Tool

Undress AI Tool

Images de déshabillage gratuites

Clothoff.io

Clothoff.io

Dissolvant de vêtements AI

Video Face Swap

Video Face Swap

Échangez les visages dans n'importe quelle vidéo sans effort grâce à notre outil d'échange de visage AI entièrement gratuit !

Outils chauds

Bloc-notes++7.3.1

Bloc-notes++7.3.1

Éditeur de code facile à utiliser et gratuit

SublimeText3 version chinoise

SublimeText3 version chinoise

Version chinoise, très simple à utiliser

Envoyer Studio 13.0.1

Envoyer Studio 13.0.1

Puissant environnement de développement intégré PHP

Dreamweaver CS6

Dreamweaver CS6

Outils de développement Web visuel

SublimeText3 version Mac

SublimeText3 version Mac

Logiciel d'édition de code au niveau de Dieu (SublimeText3)

PHP et Python: différents paradigmes expliqués PHP et Python: différents paradigmes expliqués Apr 18, 2025 am 12:26 AM

PHP est principalement la programmation procédurale, mais prend également en charge la programmation orientée objet (POO); Python prend en charge une variété de paradigmes, y compris la POO, la programmation fonctionnelle et procédurale. PHP convient au développement Web, et Python convient à une variété d'applications telles que l'analyse des données et l'apprentissage automatique.

Choisir entre PHP et Python: un guide Choisir entre PHP et Python: un guide Apr 18, 2025 am 12:24 AM

PHP convient au développement Web et au prototypage rapide, et Python convient à la science des données et à l'apprentissage automatique. 1.Php est utilisé pour le développement Web dynamique, avec une syntaxe simple et adapté pour un développement rapide. 2. Python a une syntaxe concise, convient à plusieurs champs et a un écosystème de bibliothèque solide.

Peut-on exécuter le code sous Windows 8 Peut-on exécuter le code sous Windows 8 Apr 15, 2025 pm 07:24 PM

VS Code peut fonctionner sur Windows 8, mais l'expérience peut ne pas être excellente. Assurez-vous d'abord que le système a été mis à jour sur le dernier correctif, puis téléchargez le package d'installation VS Code qui correspond à l'architecture du système et l'installez comme invité. Après l'installation, sachez que certaines extensions peuvent être incompatibles avec Windows 8 et doivent rechercher des extensions alternatives ou utiliser de nouveaux systèmes Windows dans une machine virtuelle. Installez les extensions nécessaires pour vérifier si elles fonctionnent correctement. Bien que le code VS soit possible sur Windows 8, il est recommandé de passer à un système Windows plus récent pour une meilleure expérience de développement et une meilleure sécurité.

L'extension VScode est-elle malveillante? L'extension VScode est-elle malveillante? Apr 15, 2025 pm 07:57 PM

Les extensions de code vs posent des risques malveillants, tels que la cachette de code malveillant, l'exploitation des vulnérabilités et la masturbation comme des extensions légitimes. Les méthodes pour identifier les extensions malveillantes comprennent: la vérification des éditeurs, la lecture des commentaires, la vérification du code et l'installation avec prudence. Les mesures de sécurité comprennent également: la sensibilisation à la sécurité, les bonnes habitudes, les mises à jour régulières et les logiciels antivirus.

Le code Visual Studio peut-il être utilisé dans Python Le code Visual Studio peut-il être utilisé dans Python Apr 15, 2025 pm 08:18 PM

VS Code peut être utilisé pour écrire Python et fournit de nombreuses fonctionnalités qui en font un outil idéal pour développer des applications Python. Il permet aux utilisateurs de: installer des extensions Python pour obtenir des fonctions telles que la réalisation du code, la mise en évidence de la syntaxe et le débogage. Utilisez le débogueur pour suivre le code étape par étape, trouver et corriger les erreurs. Intégrez Git pour le contrôle de version. Utilisez des outils de mise en forme de code pour maintenir la cohérence du code. Utilisez l'outil de liaison pour repérer les problèmes potentiels à l'avance.

Comment exécuter des programmes dans Terminal Vscode Comment exécuter des programmes dans Terminal Vscode Apr 15, 2025 pm 06:42 PM

Dans VS Code, vous pouvez exécuter le programme dans le terminal via les étapes suivantes: Préparez le code et ouvrez le terminal intégré pour vous assurer que le répertoire de code est cohérent avec le répertoire de travail du terminal. Sélectionnez la commande Run en fonction du langage de programmation (tel que Python de Python your_file_name.py) pour vérifier s'il s'exécute avec succès et résoudre les erreurs. Utilisez le débogueur pour améliorer l'efficacité du débogage.

Python vs JavaScript: la courbe d'apprentissage et la facilité d'utilisation Python vs JavaScript: la courbe d'apprentissage et la facilité d'utilisation Apr 16, 2025 am 12:12 AM

Python convient plus aux débutants, avec une courbe d'apprentissage en douceur et une syntaxe concise; JavaScript convient au développement frontal, avec une courbe d'apprentissage abrupte et une syntaxe flexible. 1. La syntaxe Python est intuitive et adaptée à la science des données et au développement back-end. 2. JavaScript est flexible et largement utilisé dans la programmation frontale et côté serveur.

Peut-on utiliser pour mac Peut-on utiliser pour mac Apr 15, 2025 pm 07:36 PM

VS Code est disponible sur Mac. Il a des extensions puissantes, l'intégration GIT, le terminal et le débogueur, et offre également une multitude d'options de configuration. Cependant, pour des projets particulièrement importants ou un développement hautement professionnel, le code vs peut avoir des performances ou des limitations fonctionnelles.

See all articles