Maison > Article > développement back-end > Comment gérer les problèmes de portée variable dans les fermetures Lambda non imbriquées ?
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.
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.
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.
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 :
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!