"Si un ouvrier veut bien faire son travail, il doit d'abord affûter ses outils." - Confucius, "Les Entretiens de Confucius. Lu Linggong"
Page de garde > La programmation > Comment gérer les problèmes de portée variable dans les fermetures Lambda non imbriquées ?

Comment gérer les problèmes de portée variable dans les fermetures Lambda non imbriquées ?

Publié le 2024-11-07
Parcourir:675

How to Handle Variable Scoping Issues in Non-Nested Lambda Closures?

Portée des fermetures Python Lambda

Problème

Encapsuler des variables dans des fermetures pour les supprimer des signatures de fonction est une technique souvent utilisée pour une structuration efficace du code. Cependant, dans le cas de lambdas non imbriquées, la fermeture conserve la valeur finale de la variable, ce qui entraîne des problèmes lors de la tentative d'accès à des valeurs spécifiques basées sur la variable itérative.

Considérez l'extrait de code fourni :

names = ['a', 'b', 'c']

def test_fun(name, x):
    print(name, x)

def gen_clousure(name):
    return lambda x: test_fun(name, x)

funcs1 = [gen_clousure(n) for n in names]
funcs2 = [lambda x: test_fun(n, x) for n in names]

# Expected output for funcs1
for f in funcs1:
    f(1)

# Unexpected output for funcs2 (returns last element for all cases)
for f in funcs2:
    f(1)

Comprendre la raison de cet écart est crucial pour une utilisation efficace des fermetures.

Réponse

Le concept fondamental dans cette situation est portée variable dans les fermetures . Les fermetures contiennent intrinsèquement les noms de variables plutôt que leurs valeurs. Cela signifie que l'évaluation de la variable se produit au début de l'exécution de lambda, plutôt qu'au moment de la définition de lambda.

Dans le cas de funcs2, lorsque vous exécutez lambda x : test_fun(n, x), la variable n n’est pas évalué lors de la définition lambda. Au lieu de cela, l'évaluation n'a lieu que lors de l'appel lambda. À ce stade, n contient la dernière valeur de la boucle (qui est « c » dans ce cas). Par conséquent, la fonction f utilise toujours « c » comme valeur de n, quelle que soit l'entrée x.

Pour résoudre ce problème et obtenir la fonctionnalité souhaitée, la variable n doit être capturée dans la portée de la fonction lambda. Ceci peut être réalisé en passant la variable comme argument au lambda, comme illustré dans ce qui suit :

funcs2 = [lambda x: test_fun(n, x) for n in names if 2 > 0]

En incluant cette instruction if supplémentaire qui est toujours vraie, nous forçons le lambda à prendre la valeur de n comme argument, garantissant le comportement personnalisé attendu dans tous les cas.

Alternative avec Wrapped Lambda

Vous pouvez également envelopper le lambda non imbriqué dans une fonction imbriquée, empêchant ainsi l'accès aux variables non déclarées dans la portée. Le code suivant illustre cette approche :

def makeFunc(n):
    return lambda x: x n

stuff = [makeFunc(n) for n in [1, 2, 3]]

for f in stuff:
    print(f(1))

Ici, la variable n est capturée dans la fonction makeFunc, garantissant une portée appropriée au sein du lambda.

Conclusion

Comprendre et gérer la portée des variables dans les fermetures est essentiel pour une conception et un débogage efficaces du code. Les principaux points à retenir sont :

  • Les fermetures contiennent des noms de variables, pas des valeurs
  • L'évaluation des variables se produit lors de l'exécution de lambda
  • Pour capturer les variables, transmettez-les comme arguments ou enveloppez-les le lambda dans une autre fonction
Déclaration de sortie Cet article est réimprimé à l'adresse : 1729483641. En cas d'infraction, veuillez contacter [email protected] pour le supprimer.
Dernier tutoriel Plus>

Clause de non-responsabilité: Toutes les ressources fournies proviennent en partie d'Internet. En cas de violation de vos droits d'auteur ou d'autres droits et intérêts, veuillez expliquer les raisons détaillées et fournir une preuve du droit d'auteur ou des droits et intérêts, puis l'envoyer à l'adresse e-mail : [email protected]. Nous nous en occuperons pour vous dans les plus brefs délais.

Copyright© 2022 湘ICP备2022001581号-3