عودة - بيثون ، سؤال قيمة الإرجاع
سؤال
أدرك أن هذا قد يبدو وكأنه سؤال سخيف ، لكن في المرة الأخيرة التي قمت برمجتها في التجميع ، قد يكون تفكيري متوقفًا:
وظيفة عودية مثل:
def fac(n):
if n == 0:
return 1
else:
return n * fac(n - 1)
لماذا هو أنه عندما تصل الوظيفة إلى n == 0 ، فإنها لا تعود 1 بل الإجابة التي هي العازلة. أفكر في شيء مثل في المجمع ، سيكون عندما يكون n == 0:
mov eax, 1
ret
لماذا يعمل الرمز أعلاه ، أفترض أن Python يعيد القيمة الأخيرة على المكدس قبل هذا الشرط؟
المحلول
فكر في مثل هذا ، ل fac(5)
فمثلا:
return 5 * fac(4)
return 4 * fac(3)
return 3 * fac(2)
return 2 * fac(1)
return 1 * fac(0)
1
لذا 1
سيكون ال أول القيمة التي تم إرجاعها ولكن سيتم إعادتها إلى fac(1)
و fac(1)
سيتم إعادته إلى fac(2)
وهلم جرا.
نصائح أخرى
هو - هي يفعل إرجاع 1 عند n == 0. يتم برز قيمة الإرجاع هذه من موقع الاتصال ، والذي كان الاحتجاج في n * fac(n - 1)
. الذي - التي 1
مضروب من قبل n
وعاد ، إلخ
إذا اتصلت بـ FAC (0) ، فسيعود 1 (وليس 0 ، لكنني أفترض أن هذا مجرد خطأ مطبعي في سؤالك). إذا اتصلت بـ FAC (1) ، فستذهب في الفقرة الأخرى ، وسيتصل بها fac(0)
. سيعود هذا 1. بعد ذلك سيحسب n*1 ، وهو 1 ، وإرجاع ذلك. إذا اتصلت fac(2)
سوف يذهب أيضا في الفقرة الأخرى ، حيث سيتم الاتصال fac(1)
ما هو مذكور أعلاه سيعود 1 ، لذلك n*fac(n-1)
سيكون 2 وهذه هي قيمة الإرجاع fac(2)
. وهلم جرا. آمل أن شرح ذلك لك.
لا شيء يتم إرجاعه بشكل ضمني - عندما ن = 0 ، تدخل الوظيفة إلى البيان IF ، والعودة 1 مباشرة من return 1
بيان. ومع ذلك ، فإن هذه ليست النقطة التي يتم فيها إرجاع "الإجابة التي هي العامل" إلى المستخدم. بدلاً من ذلك ، قد يعيد هذه القيمة إلىالدعوة الوظيفة التي تم استدعاؤها بواسطة FAC (1) ، والتي في منتصف n * fac(n - 1)
فرع. وبالتالي سوف يستغرق "1" عاد والعودة n*1
, ، وهو 1 إلى إنه المتصل. إذا كان هذا هو الوجه (2) ، فسوف يعود n * 1
, أو 2 إلى إنه المتصل وهلم جرا.
وهكذا يتم ترجمة FAC (5) مثل:
fac(5) = 5 * fac(4) = 5 * (4 * fac(3) = 5 * (4* (3 * fac(2)) = 5 * (4* (3 * (2 * fac(1)) = 5 * (4* (3 * (2 * (1 * fac(0)) = 5*4*3*2*1*1
فقط بعد إرجاع القيمة 1 من خلال كل طبقة علوية ، تعود إلى المتصل الأول ، ويمنحك الضرب في كل مرحلة الإجابة.
جيمس ، عندما تعيد المكالمة النهائية إلى وظيفتك (عند n == 0) ، فهي مجرد واحدة من عدة مثيلات من FAC (n) على مكدس الاتصال. إذا قلت الطباعة (FAC (4)) ، فإن المكدس هو بشكل أساسي:
fac(0)
fac(1)
fac(2)
fac(3)
fac(4)
print()
إرجاع المكالمة النهائية لـ FAC (0) بشكل مناسب 1 ، ولكن في Python ، طلبت قيمة الإرجاع للمكالمة الأولى لـ FAC (N) ، FAC (4).
لا تفكر في الأمر كحلقة حيث ستندلع "Ret" ، فإن العودة ببساطة تختتم واحدة من العديد من عمليات الإعدام المعلقة.