يعد تغليف المتغيرات داخل عمليات الإغلاق لإزالتها من توقيعات الوظائف تقنية تستخدم غالبًا لهيكلة التعليمات البرمجية الفعالة. ومع ذلك، في حالة معاملات lambda غير المتداخلة، يحتفظ الإغلاق بالقيمة النهائية للمتغير، مما يؤدي إلى حدوث مشكلات عند محاولة الوصول إلى قيم محددة بناءً على المتغير التكراري.
ضع في الاعتبار مقتطف التعليمات البرمجية المقدم:
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)
يعد فهم السبب الكامن وراء هذا التناقض أمرًا بالغ الأهمية لاستخدام الإغلاق الفعال.
المفهوم الأساسي في هذه الحالة هو النطاق المتغير في عمليات الإغلاق . تحتوي عمليات الإغلاق بطبيعتها على أسماء المتغيرات بدلاً من قيمها. وهذا يعني أن تقييم المتغير يحدث عند بدء تنفيذ لامدا، وليس في وقت تعريف لامدا.
في حالة funcs2، عند تنفيذ لامدا x: test_fun(n, x)، المتغير n لم يتم تقييمه أثناء تعريف لامدا. وبدلاً من ذلك، يتم التقييم فقط عند استدعاء lambda. عند هذه النقطة، يحتفظ n بالقيمة الأخيرة من الحلقة (وهي 'c' في هذه الحالة). ونتيجة لذلك، تستخدم الدالة f دائمًا 'c' كقيمة n، بغض النظر عن الإدخال x.
لمعالجة هذه المشكلة وتحقيق الوظيفة المطلوبة، يجب التقاط المتغير n في نطاق دالة لامدا. يمكن تحقيق ذلك عن طريق تمرير المتغير كوسيطة إلى lambda، كما هو موضح في ما يلي:
funcs2 = [lambda x: test_fun(n, x) for n in names if 2 > 0]
من خلال تضمين عبارة if الإضافية التي تظل صحيحة دائمًا، فإننا نجبر lambda على أخذ قيمة n كوسيطة، مما يضمن السلوك الشخصي المتوقع في جميع الحالات.
بدلاً من ذلك، يمكنك لف lambda غير المتداخلة في وظيفة متداخلة، مما يمنع بشكل فعال الوصول إلى المتغيرات غير المعلنة في النطاق. توضح التعليمة البرمجية التالية هذا الأسلوب:
def makeFunc(n): return lambda x: x n stuff = [makeFunc(n) for n in [1, 2, 3]] for f in stuff: print(f(1))
هنا، يتم التقاط المتغير n في الدالة makeFunc، مما يضمن تحديد النطاق المناسب داخل لامدا.
فهم نطاق المتغير وإدارته في عمليات الإغلاق ضروري لتصميم التعليمات البرمجية وتصحيح الأخطاء بشكل فعال. الوجبات الرئيسية هي:
تنصل: جميع الموارد المقدمة هي جزئيًا من الإنترنت. إذا كان هناك أي انتهاك لحقوق الطبع والنشر الخاصة بك أو الحقوق والمصالح الأخرى، فيرجى توضيح الأسباب التفصيلية وتقديم دليل على حقوق الطبع والنشر أو الحقوق والمصالح ثم إرسالها إلى البريد الإلكتروني: [email protected]. سوف نتعامل مع الأمر لك في أقرب وقت ممكن.
Copyright© 2022 湘ICP备2022001581号-3