--- title: Nested Functions in Python localeTitle: وظائف متداخلة في بيثون --- ### مساحات تمثل معلمات الدالة ، بالإضافة إلى أي متغيرات مرتبطة (بواسطة تخصيص أو بواسطة عبارات ملزمة أخرى ، مثل def) في نص الدالة ، مساحة الاسم المحلية للوظيفة ، والتي تعرف أيضًا باسم النطاق المحلي. ويعرف كل من هذه المتغيرات كمتغير محلي للدالة. تعرف المتغيرات غير المحلية بالمتغيرات العامة (في غياب تعريفات الدالة المتداخلة ، والتي سنناقشها بعد قليل). المتغيرات العمومية هي سمات كائن الوحدة النمطية ، كما تم تغطيتها في "سمات كائنات الوحدة النمطية" في الصفحة 140. عندما يكون للمتغير المحلي الخاص بالوظيفة نفس الاسم كمتغير عمومي ، يشير هذا الاسم ، داخل نص الدالة ، إلى المتغير المحلي ، ليس العالم. نحن نعبر عن هذا بالقول أن المتغير المحلي يخفي المتغير الشامل الذي يحمل نفس الاسم في جسم الوظيفة. ### البيان العالمي بشكل افتراضي ، أي متغير مرتبط داخل جسم دالة هو متغير محلي للدالة. إذا احتاجت إحدى الوظائف إلى إعادة بث بعض المتغيرات العامة ، فيجب أولاً يجب أن يكون بيان الوظيفة كما يلي: معرفات عالمية حيث المعرفات هي واحد أو أكثر من المعرفات مفصولة بفواصل (،). تشير المعرّفات المدرجة في بيان عالمي إلى المتغيرات العامة (أي سمات كائن الوحدة النمطية) التي تحتاج الدالة إلى إعادة بثها. على سبيل المثال ، يمكن تنفيذ عداد الدالة الذي رأيناه في "سمات أخرى لكائنات الدالة" في صفحة 73 باستخدام المتغير العام والمتغير العام ، بدلاً من سمة كائن الدالة: \_count = 0 def counter (): عالمي \_ عدد \_count + = 1 عودة \_count بدون العبارة العمومية ، سترفع الدالة العداد استثناء UnboundLocal- خطأ لأن \_count سيكون متغير محلي غير مهيأ (غير منضم). في حين أن البيان العالمي يمكّن هذا النوع من البرمجة ، فإن هذا النمط غالباً ما يكون غير متناسق وغير مرغوب فيه. كما ذكرت سابقًا ، عندما تريد تجميع بعض الحالات وبعض السلوكيات ، تكون الآليات الموجهة للكائنات في الفصل 5 عادةً أفضل. لا تستخدم العمومية إذا كان جسم الدالة يستخدم فقط متغيرًا عامًا (بما في ذلك تحوير الكائن المرتبط بهذا المتغير إذا كان الكائن قابلاً للتغيير). استخدم عبارة عامة فقط في حالة قيام جسم الدالة بتكرار متغير عام (بشكل عام عن طريق تعيين اسم المتغير). كمسألة أسلوب ، لا تستخدم عالميًا إلا إذا كان ذلك ضروريًا تمامًا ، نظرًا لأن وجودها سيؤدي إلى أن يقرِّر برنامجك أن البيان موجود لغرض مفيد. على وجه الخصوص ، لا تستخدم عالميًا باستثناء العبارة الأولى في نص وظيفة. {عنوان mospagebreak = وظائف متداخلة ونطاقات متداخلة} تعرف عبارة def (def def) في جسم دالة دالة متداخلة ، وتعرف الدالة التي يتضمن جسمها def كوظيفة خارجية إلى الدالة المتداخلة. قد يدخل الرمز الموجود في جسم الدالة المتداخلة (ولكن ليس التكرار) المتغيرات المحلية لدالة خارجية ، والتي تعرف أيضًا باسم المتغيرات المجانية للدالة المتداخلة. إن أبسط طريقة للسماح لدالة متداخلة بالوصول إلى قيمة لا تعتمد في الغالب على نطاقات متداخلة ، ولكن بدلاً من تمرير هذه القيمة بشكل صريح كواحدة من وسائط الدالة. إذا لزم الأمر ، يمكن ربط قيمة الوسيطة عندما يتم تعريف الدالة المتداخلة باستخدام القيمة على أنها القيمة الافتراضية لوسيطة اختيارية. فمثلا: def percent1 (a، b، c): def pc (x، total = a + b + c): return (x \* 100.0) / total الطباعة "النسب المئوية هي:" ، أجهزة الكمبيوتر (أ) ، وأجهزة الكمبيوتر (ب) ، وأجهزة الكمبيوتر (ج) إليك الوظيفة نفسها باستخدام النطاقات المتداخلة: def percent2 (a، b، c): def pc (x): return (x \* 100.0) / (a ​​+ b + c) الطباعة "النسب المئوية هي:" ، أجهزة الكمبيوتر (أ) ، وأجهزة الكمبيوتر (ب) ، وأجهزة الكمبيوتر (ج) في هذه الحالة المحددة ، يكون لدى النسبة المئوية 1 ميزة صغيرة: يحدث حساب a + b + c مرة واحدة فقط ، بينما يكرر الكمبيوتر الداخلي ذو الوظائف المئوية في الحصة ثلاث مرات. ومع ذلك ، إذا كانت الدالة الخارجية تقوم بتجريد المتغيرات المحلية الخاصة بها بين الاستدعاءات إلى الدالة المتداخلة ، فيمكن أن يكون تكرار الحساب ضروريًا. لذلك من المستحسن أن تكون على دراية بكلا النهجين ، واختيار الحالة الأكثر ملاءمة لكل حالة على حدة. تعرف أيضًا الدالة المتداخلة التي تصل إلى القيم من المتغيرات المحلية الخارجية باسم الإغلاق. يوضح المثال التالي كيفية إنشاء إغلاق: def\_adder def (augend): def add (addend): إضافة الإضافة + أوجند العودة إضافة عمليات الإغلاق هي استثناء للقاعدة العامة بأن الآليات الموجهة للكائنات التي يغطيها الفصل الخامس هي أفضل طريقة لتجميع البيانات والشفرات معاً. عندما تحتاج على وجه التحديد إلى إنشاء كائنات قابلة للاستدعاء ، مع بعض المعلمات التي تم إصلاحها في وقت بناء الكائن ، يمكن أن تكون عمليات الإغلاق أكثر بساطة وفعالية من الفئات. على سبيل المثال ، تكون نتيجة make\_adder (7) دالة تقبل وسيطة واحدة وتضيف 7 إلى هذه الوسيطة. تعتبر الدالة الخارجية التي تعيد الإغلاق "مصنعًا" لأعضاء مجموعة من الوظائف المتميزة ببعض المعلمات ، مثل قيمة الوسيط المعجزة في المثال السابق ، وقد تساعدك في الغالب على تجنب تكرار الكود. ### تعبيرات لامدا إذا كان نص الدالة عبارة تعبير واحد ، فيمكنك اختيار استبدال الوظيفة بنموذج التعبير lambda الخاص: معلمات lambda: التعبير تعبير lambda هو المعادل المجهول للدالة العادية التي يكون جسدها عبارة إرجاع واحدة. لاحظ أن بناء الجملة lambda لا يستخدم الكلمة الأساسية المرجعة. يمكنك استخدام تعبير lambda حيثما يمكنك استخدام مرجع لوظيفة. يمكن أن تكون lambda مفيدة في بعض الأحيان عندما تريد استخدام وظيفة بسيطة كحجة أو قيمة إرجاع. في ما يلي مثال يستخدم تعبير lambda كوسيطة لوظيفة التصفية المضمنة (المغطاة في الفلتر في الصفحة 161): aList = \[1 ، 2 ، 3 ، 4 ، 5 ، 6 ، 7 ، 8 ، 9\] منخفض = 3 عالية = 7 عامل التصفية (lambda x، l = low، h = high: h> x> l، aList) # returns: \[4، 5، 6\] وكبديل ، يمكنك دائمًا استخدام عبارة def محلية تعطي اسم الدالة كائنًا. يمكنك بعد ذلك استخدام هذا الاسم كوسيطة أو قيمة إرجاع. في ما يلي مثال الفلتر نفسه باستخدام عبارة def def: aList = \[1 ، 2 ، 3 ، 4 ، 5 ، 6 ، 7 ، 8 ، 9\] منخفض = 3 عالية = 7 def ضمن _الحدود (القيمة ، l = low ، h = high): return h> value> l عامل التصفية (ضمن_ الحدود ، القائمة) # يرجع: \[4 ، 5 ، 6\] في حين أن lambda يمكن أن تكون مفيدة في بعض الأحيان ، يفضل العديد من مستخدمي Python def ، وهو أكثر عمومية ، وقد يجعل كودك أكثر قابلية للقراءة إذا اخترت اسمًا معقولًا للدالة. {mospagebreak title = Generators} عندما يحتوي جسم الدالة على واحد أو أكثر من مرات حدوث ناتج الكلمة الرئيسية ، تُعرف الدالة باسم المولد. عند استدعاء مولد ، لا يتم تنفيذ نص الدالة. وبدلاً من ذلك ، يقوم استدعاء المولد بإرجاع كائن مكوّن خاص يلف جسم الوظيفة ، والمتغيرات المحلية (بما في ذلك المعلمات) ، ونقطة التنفيذ الحالية ، وهي بداية تشغيل الدالة. عندما يتم استدعاء الأسلوب التالي لكائن التكرار هذا ، ينفذ جسم الدالة حتى بيان العائد التالي ، والذي يأخذ النموذج: التعبير العائد عند تنفيذ بيان العائد ، يتم "تنفيذ التعليمة" ، مع نقطة التنفيذ الحالية والمتغيرات المحلية سليمة ، ويتم إرجاع التعبير بعد العائد كنتيجة للطريقة التالية. عندما يتم استدعاء التالي مرة أخرى ، يستأنف تنفيذ جسم الوظيفة حيث توقفت ، مرة أخرى حتى بيان العائد التالي. في حالة انتهاء نص الدالة أو تنفيذ عبارة return ، يقوم المكافئ بإصدار استثناء StopIteration للإشارة إلى انتهاء التكرار. لا يمكن أن تحتوي عبارات الإرجاع في مولد على تعبيرات. مولد هو وسيلة سهلة جدا لبناء مكرر. نظرًا لأن الطريقة الأكثر شيوعًا لاستخدام مكرر البيانات هي التكرار باستخدام عبارة for ، فإنك عادةً ما تتصل بمولد مثل هذا: للمتغير في somegenerator (الحجج): على سبيل المثال ، قل أنك تريد تسلسلًا من الأرقام من 1 إلى N ثم إلى 1 مرة أخرى. يمكن أن يساعد المولد في: def updown (N): لـ x في xrange (1، N): yield x لـ x في xrange (N، 0، -1): الإنتاجية x لأني في updown (3): print i # printts: 1 2 3 2 1 هنا مولد يعمل إلى حد ما مثل وظيفة xrange المضمنة ، لكنه يعيد سلسلة من قيم الفاصلة العائمة بدلاً من تسلسل من الأعداد الصحيحة: defange frange (start، stop، step = 1.0): بينما تبدأ