Maison  >  Article  >  développement back-end  >  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 ?

Barbara Streisand
Barbara Streisandoriginal
2024-10-21 13:10:03594parcourir

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 pour prendre la valeur de n comme argument, garantissant le comportement personnalisé attendu dans tous les cas.

Alternative avec Wrapped Lambda

Alternativement, vous pouvez envelopper le lambda non imbriqué dans un imbriqué fonction, empêchant efficacement 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

Compréhension et la gestion de la portée des variables dans les fermetures est essentielle 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

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:
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