Qu'est-ce qu'une fermeture ? Deux solutions aux problèmes liés aux fermetures Python

Y2J
Libérer: 2017-05-04 14:54:33
original
1499 Les gens l'ont consulté

La fermeture consiste à obtenir des résultats différents en fonction de différentes informations de configuration. Permettez-moi de partager avec vous deux notes sur les fermetures Python à travers cet article. Les amis dans le besoin peuvent se référer à

Qu'est-ce qu'une fermeture ?

Simple. Cela dit, la fermeture consiste à obtenir des résultats différents basés sur différentes informations de configuration.

Regardons l'explication professionnelle : Closure est l'abréviation de Lexical Closure, qui est un qui fait référence à une variable libre Fonction. La variable libre référencée restera avec la fonction même après avoir quitté l'environnement dans lequel elle a été créée. Il existe donc une autre façon de dire qu’une fermeture est une entité composée d’une fonction et de son environnement de référence associé.

Liaison paresseuse Les variables libres externes référencées par les fonctions de fermeture Python sont liées paresseusement.

Python

Comme indiqué dans le code ci-dessus : i est une variable libre dans la portée externe référencée par la fonction de fermeture, ce qui n'arrivera que lorsque la
In [2]: def multipliers():
  ...:   return [lambda x: i * x for i in range(4)] 
In [3]: print [m(2) for m in multipliers()]
[6, 6, 6, 6]
In [2]: def multipliers():
  ...:   return [lambda x: i * x for i in range(4)] 
In [3]: print [m(2) for m in multipliers()]
[6, 6, 6, 6]
Copier après la connexion
fonction interne

est appelé recherche la valeur de variable i. Puisque la boucle est terminée et que i pointe vers la valeur finale 3, chaque appel de fonction obtient le même résultat.

Solution :

1) Lier immédiatement lors de la génération de la fonction de fermeture (

Utiliser la valeur par défaut de la fonction

paramètre formel) : Python

Comme le code ci-dessus : Lors de la génération d'une fonction de fermeture, vous pouvez voir que chaque fonction de fermeture a un paramètre avec une valeur par défaut : i=i, à ce moment, expliquez Le Le compilateur trouvera la valeur de i et l'attribuera au paramètre formel i. De cette façon, dans la portée externe de la fonction de fermeture générée (c'est-à-dire dans la boucle externe), la variable i est trouvée et sa valeur actuelle est attribué au paramètre formel i.
In [5]: def multipliers():
  return [lambda x, i=i: i* x for i in range(4)]
    ...: 
In [6]: print [m(2) for m in multipliers()]
[0, 2, 4, 6]
In [5]: def multipliers():
  return [lambda x, i=i: i* x for i in range(4)]
    ...: 
In [6]: print [m(2) for m in multipliers()]
[0, 2, 4, 6]
Copier après la connexion

2) Utilisez functools.partial :

Python

Comme le code ci-dessus : lorsqu'il peut y avoir des problèmes dus à une liaison retardée, vous pouvez utiliser functools. partial construit une fonction partielle de sorte que les variables libres soient d'abord liées à la fonction de fermeture.
In [26]: def multipliers():
  return [functools.partial(lambda i, x: x * i, i) for i in range(4)]
  ....: 
In [27]: print [m(2) for m in multipliers()]
  [0, 2, 4, 6]
In [26]: def multipliers():
  return [functools.partial(lambda i, x: x * i, i) for i in range(4)]
  ....: 
In [27]: print [m(2) for m in multipliers()]
  [0, 2, 4, 6]
Copier après la connexion

Interdire la reliure des variables libres référencées dans une fonction de fermeturePython

Ci-dessus Le code signalera un erreur, UnboundLocalError : variable locale 'free_value' référencée avant l'affectation. Le code ci-dessus est destiné à implémenter un état d'initialisation
def foo(func):
  free_value = 8
  def _wrapper(*args, **kwargs):
    old_free_value = free_value #保存旧的free_value
    free_value = old_free_value * 2 #模拟产生新的free_value
    func(*args, **kwargs)
    free_value = old_free_value
  return _wrapper
def foo(func):
  free_value = 8
  def _wrapper(*args, **kwargs):
    old_free_value = free_value #保存旧的free_value
    free_value = old_free_value * 2 #模拟产生新的free_value
    func(*args, **kwargs)
    free_value = old_free_value
  return _wrapper
Copier après la connexion

(free_value) mais peut être utilisé à la demande lors de l'exécution de la fonction de fermeture interne. nouvel état (free_value = old_free_value * 2), mais en raison de la reliure interne, l'interpréteur traitera free_value comme une variable locale. Si old_free_value = free_value, une erreur sera signalée car l'interpréteur pense que free_value n'a aucune valeur attribuée. .

Solution :

Lorsque vous prévoyez de modifier la variable libre référencée par la fonction de fermeture, vous pouvez la mettre dans une liste, donc, free_value = [8], free_value ne peut pas être modifié, mais free_value[0] peut être modifié

en toute sécurité

. De plus, Python 3.x a ajouté le mot-clé nonlocal, qui peut également résoudre ce problème.

[Recommandations associées]

1.

Tutoriel vidéo gratuit Python

2.

Manuel d'apprentissage Python

3. Tutoriel vidéo orienté objet Python

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!

Étiquettes associées:
source:php.cn
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
Tutoriels populaires
Plus>
Derniers téléchargements
Plus>
effets Web
Code source du site Web
Matériel du site Web
Modèle frontal
À propos de nous Clause de non-responsabilité Sitemap
Site Web PHP chinois:Formation PHP en ligne sur le bien-être public,Aidez les apprenants PHP à grandir rapidement!