الفريق العربي للبرمجةأرشيف المنتديات · 2000 – 2023
نسخة أرشيفية للقراءة فقط — التسجيل والمشاركة مغلقان، والمحتوى محفوظ كما كان.

استفسار او شرح عن (اﻻرتداد او العودة) Recursive

بدأه احمد وسام في 31 مايو 2014 · 21 رد · 2,341 مشاهدة · في لغة Python
مشاركة: واتساب X فيسبوك تيليجرام
#1 صاحب الموضوع

السلام عليكم

 

وصلت انا في تعلم بايثون في الكورس الخاص في اﻻستاذ ايهاب رجب الى درس اﻻرتداد

 

ﻻكني لم افهم اﻻ مثاله وعندما ابحث عن امثلة بسيطة ﻻ افهم كيف يطبقها الحاسوب

 

باختصار  مدافهمها

 

ممكن شرح لها مفهوم وامثلة لها كيف يتم تطبيقه المفسر

وخاصة هذا المثال

def factorial(n):
    if n == 1:
        return 1
    else:
        return n * factorial(n-1)

المفروض من هذا المثال

ان يضرب5*4

5*3

5*2

 

ثم ييخرج الناتج 55

 

ﻻكن الناتج يخرج في المفسر 120

ﻻنه قام بضرب جماعي

2*3*4*5

 

كيف قام بضرب جماعي

 

اتمنى المساعدة

تم تعديل هذه المشاركة بواسطة احمد وسام في 31 مايو 2014 في 23:19

#2

باختصار شديد هو استدعاء الدالة لنفسها واحسن تطبيق لذلك هو متتالية فيبوناتشي

def fibo(n):
    if n == 0: return 0
    elif n == 1: return 1
    else: return fibo(n-1)+fibo(n-2)

print fibo(6)
#3

اخي ممكن تشرحلي ماذا حصل في التطبيق

#4
احمد وسام كتب:

السلام عليكم

 

وصلت انا في تعلم بايثون في الكورس الخاص في اﻻستاذ ايهاب رجب الى درس اﻻرتداد

 

ﻻكني لم افهم اﻻ مثاله وعندما ابحث عن امثلة بسيطة ﻻ افهم كيف يطبقها الحاسوب

 

باختصار  مدافهمها

 

ممكن شرح لها مفهوم وامثلة لها كيف يتم تطبيقه المفسر

وخاصة هذا المثال

def factorial(n):
    if n == 1:
        return 1
    else:
        return n * factorial(n-1)

المفروض من هذا المثال

ان يضرب5*4

5*3

5*2

 

ثم ييخرج الناتج 55

 

ﻻكن الناتج يخرج في المفسر 120

ﻻنه قام بضرب جماعي

2*3*4*5

 

كيف قام بضرب جماعي

 

اتمنى المساعدة

 

 

المثال الذي طرحت هو لحساب العاملي لعدد ما
سانطلق من النقطة التي اعطتك مفهوما خاطئ عن مفهوم الارتداد
هو في قولك : ان يضرب5*3  وهي ثاني دورة للحلقة التكرارية في البرنامج
البرنامج حقيقة يقوم بالاحتفاظ بناتج الضرب في كل مرة ثم تكرار الحلقة مع انقاص 1 من المتغير الاول في كل مرة الى ان نصل الى الرقم 1 اين ينتهي البرنامج
#5

ﻻ يالغالي اقصدمثالك وليس مثالي

 

مالذي حصل في مثالك ارجو ان تشرح لي كما شرحت لي مثالي

#6

العودية هي الإستدعاء الثاتي للدالة  داخل الدالة

 

أب أنها يمثابة حلقة تكرارية لكي تفهم مفهوم العودية عليك أن تفهم الحلقات أولا

 

العودية تستعمل لتبسيط الحل في حالات معينة كالمتتاليات مثلا

 

و الدوال التي نستطيع تعريفها باستعمال العلاقة التراجعية

 

أي أن للقيمة الحالية علاقة بالقيمة السابقة و للسابقة علاقة بالقيمة التي قبلها و هكذا

 

مثلا نحن نريد حساب جميع الأعداد الطبيعية التي أصغر من أو تساوي n

def sum(n):
    if n==0:
        return 0
    else:
        return n+sum(n-1)

خلاصة الخلاصة أننا نستعمل العودية

 

إذا كان بإمكاننا كتابة العلاقة بعلاقة تراجعية

 

عليك أن تفهم التكرارات بشكل جيد حتي تفهم الرجعية

 

بالتطبيق ستفهم أكثر

1
#7

شأشرح العودية بشكل أكثر تفصيل

 

العودية متعلقة بالدوال و التكرارات فهي دالة تكرر نفسها

 

أولا الدوال

def sum(a):    return a+1print sum(4)print sum(1)

بالبداية عرفنا الدالة بالسطرين الأولين

 

ثم إستدعيناها يالسطرين الثالث و الرابع

 

عندما نستدعي الدالة يذهب المترجم إلى تعريف الدالة و تنقذ الكود الموجود بداخلها مع تعويض قيمة البراماتر(a) بالقيمة الموجودة في الإستدعاء

 

ثانيا التكرارات

 

التكرارات هي تكرار تعليمة أو تعليمات لعدد من المرات

 

يمكن أن بشمل هذا التكرار على متغيرات

 

مثلا نحن نريد حساب مجموع الأرقام من 1 إلى x 

x=input('x :')b=1while b<=x:    b=b+1print b

الأن نأتي للعودية

 

العودية هي الإستدعاء الذاتي للدالة أي في الكود الموجود داخل الدالة يوجد إستدعاء للدالة

 

مثلا نطبق نفس المثال الثاني في العودية باستخدام المثال الأول

def sum(a):
    if a==0:
        return 0
    else:
        return a+sum(a-1)
print sum(2)

سأبدأ بالشرخ من آخر سطر

 

هذا إستدعاء للدالة

 

كما قلت سابقا المترجم يذهب للدالة و بنفذ ما بداخلها بتعويض قيمة البراماتر بالمتغير الموجود بالإستدعاء

 

الأن المترجم ذهب للدالة عوض البراماتر ب 2

 

بالبداية لدينا شرط (هذا الشرط غير مجقق لأن 2 أكبر من ال 0)

 

فيذهب للسطر الذي بعده

 

هنا لدينا تعليمة إرجاع قيمة(return)

 

و القيمو المرجعة هي 2+( sum(2-1

 

هذا إستدعاء آخر للدالة

 

الدالة قبل إرجاع هذه القيمة لابد لخا من حسابها أولا و لحسابها فهي تحتاج لقيمة( sum(1

 

لذا فإن المترجم يستدعي الدالة من جيد بالبراماتر واحد

 

و من جيد الشرط غير محقق لأن 1>0

 

فيذهب للتعليمة التي بعدها فيجد إستدعاء آخر للدالة

 

فيذهب للدالة و ينفذ الكود الموجود بالدالة بتعويض قيمة الباراماتر ب ال 0

 

الأن الشرط محقق و الدالة ترجع القيمة 1

 

المترجم يسجل هذه القيمة و يعود لمكان الإستدعاء الثاني و يحسب 1+1 و يحتفظ بالناتج و يعود لإستدعاء الأول و يحسب 2+1 و يرجع الناتج

 

أرجو أن تكون قد فهمت و إن لم تفهم سأكتب شرحا بالصور بعد تفرغي من أعمالي

تم تعديل هذه المشاركة بواسطة kenham في 1 يونيو 2014 في 01:53

#8

لا كفيت ووفيت يالغالي وصلت

 

ﻻكن سؤال

 

انت قلت يرجع القيمة

 

1+1

 

من اين اتى رقم 1 اﻻخر

 

اذ كانت النتيجة فقط 1

#9
return a+sum(a-1)

القمية المرجعة من الإستدعاء هي 1

 

لكن هذه القيمة مجموعة مع a  كما ترى

 

بالمناسبة لقد أخطأت في برمجة العودية

 

كان على أن أضع

 

return 0

 

و ليس

return 1

 

سأصححه الآن

1
#10

اشكرك وتعبتك اخي معي جزاك الله خير

#11
def a(n):
	if len(n) < 1:
		return n
	else:
		return n[0]+' '+a(n[1:])

ناتج هذا المثال هو وضع مساافات بين الحروف

 

h e l l o

 

ﻻكن سؤال

        return n[0]+' '+a(n[1:])

هنا واضع مسافة فقط بين الحرف اﻻول والثاني

 

واذا تكررت رح يتكرر ايضا وضع مسافة بين الحرف اﻻول والثاني

 

السؤال كيف وضع المسافة بين الحروف كلها

تم تعديل هذه المشاركة بواسطة احمد وسام في 1 يونيو 2014 في 03:42

#12

هناك فرق كبير بين الإستدعاء الذاتي الذاتي وحلقات التكرار. لكي تفهم كيف يعمل الإستدعاء الذاتي، يلزمك أن تفهم كيف تستدعى الدالة وماهو الـactivation record/stack frame (موضوع متقدم ولا لا أملك الوقت حالياً لتوضيحه).

 

عموماً إذا كانت المشكلة التي لديك يمكن حلها باستخدام حلقات التكرار فلا تستخدم الإستدعاء الذاتي، فهو يستهلك الذاكرة.

 

مثال على حالة تتطلب استدعاء ذاتي، لدي قائمة شكلها كالتالي:

l = [1, [2, [3, [4]]]]

وأريد طباعة الأرقام التي في القائمة، حلقة التكرار لن تنفع هنا:

>>> l = [1, [2, [3, [4]]]]
>>>
>>> for n in l:
...     print(n)
...
1
[2, [3, [4]]]
>>>

يمكن حل هذه المشكلة عن طريق الإستدعاء الذاتي:

>>> l = [1, [2, [3, [4]]]]
>>>
>>> def dump(lst):
...     for i in lst:
...         # هل هذا العنصر قائمة؟
...         if isinstance(i, list):
...             # تشعب
...             dump(i)
...         else:
...             print(i)
...
>>>
>>> dump(l)
1
2
3
4
>>>

تمر على عناصر القائمة، إذا وجدت العنصر قائمة، فتستدعي الدالة مرة أخرى مع هذا العنصر (كأنك تتشعب داخل شجرة).

 

حتى المشاكل التي تتطلب استدعاء ذاتي يمكن حلها بدونه عن طريق المكدس (محاكاة لمكدس الدالة)، نفس الحل السابق باستخدام المكدس:

>>> l = [1, [2, [3, [4]]]]
>>>
>>> def dump(lst):
...     stack = []
...     stack.append(lst)
...     while len(stack) > 0:
...         curr = stack.pop()
...         for i in curr:
...             if isinstance(i, list):
...                 stack.append(i)
...             else:
...                 print(i)
...
>>> dump(l)
1
2
3
4
>>>
2
#13

اشكرك اخي على شرحك المتواضع

ﻻكن لدي سؤال

 

كيف استطاعت انت تطبع العنصر دالة isunstance

 

مع العلم هي ترد بقيمة True << False

 

ممكن توضيح

#14

لم أفهمك، لكن isinstance يمكن استخدامها لمعرفة نوع الكائن (إذا كان يرث من فئة معينة)، مثلاً:

 

>>> n = 1
>>>
>>> isinstance(n, int)
True
>>> isinstance(n, str)
False
>>> isinstance(n, float)
False
>>>
>>> n = 'ABCD'
>>>
>>> isinstance(n, int)
False
>>> isinstance(n, str)
True
>>> isinstance(n, float)
False
>>>

 

لا تشغل بالك كثير بموضوع الـrecursion لأنك غالباً لن تحتاجه حالياً، متى ماتقدمت واحتجته رايح يوضح لك.

#15

صحيح اخي وانا في بداية تعلمي لبايثون ومتجه ﻻختصاص الويب !!

ﻻكن انا كان من سؤالي

 

كيف انها راح تطبع رقم العنصر

 

مع العلم انها تطبع True ,False

اي يصبح الناتج

 

True

True

True

True

 

ﻻكنها قامت بطباعة اﻻرقام

1

2

3

4

تم تعديل هذه المشاركة بواسطة احمد وسام في 1 يونيو 2014 في 13:24

#16

السلام عليكم

لدي استفسار ولو ازعجتكم ﻻكن للان انا اتعلمها واتعلم كيف يتم اضهار الناتج فيها

 

كتبت سكربت لمعرفة هل يوجد رقم في القائمة اكبر من الرقم الي اضعه

 

 

 

 

السكربت هذا

def b(y):	if any(x > b(y) for x in[5,6,3,4]):		return True	return False

عندما اكتب

a(2)

 

 

يضهر الناتج True

 

وعندما اكتب  a(8)

يضهر ايضا

True

او يخرج لي اخطاء وتستمر بالتكرار

 

وهذا خطا ﻻيوجد رقم في القائمة اكبرمن 8

ماسبب طباعته لي True وليس False

اخوان جوابكم لي بخصوص هذا السؤال راح يحل لي مشاكل كثيرة

جزاكم الله خير

 

ممكن تكتبون لي التعديل

تم تعديل هذه المشاركة بواسطة احمد وسام في 4 يونيو 2014 في 23:35

#17
اقتباس

 

كتبت سكربت لمعرفة هل يوجد رقم في القائمة اكبر من الرقم الي اضعه

 

السكربت الذي كتبته خاطئ لست أدري من أين أحضرت المتغير a

 

و هذا هو التصحيح

def b(y):
	if any(x > y for x in[5,6,3,4]):
		return True
	return False

بالمناسبة هذا الموضوع خاص بالعودية كان عليك فتح موضوع آخر  و طرح سؤالك فيه

تم تعديل هذه المشاركة بواسطة kenham في 4 يونيو 2014 في 21:25

#18
اقتباس

 

مع العلم انها تطبع True ,False

اي يصبح الناتج

 

True

True

True

True

 

ﻻكنها قامت بطباعة اﻻرقام

1

2

3

4

 

أخي الكريم إذا أردت التعلم عليك البدأ بالأساسيات

 

أنت لا تفهم حتي الجمل الشرطية

 

راجع دروس الجمل الشرطية و ستفهم

#19
kenham كتب:

أخي الكريم إذا أردت التعلم عليك البدأ بالأساسيات

 

أنت لا تفهم حتي الجمل الشرطية

 

راجع دروس الجمل الشرطية و ستفهم

 

ياخي ليست الجمل الشرطية

ارجو اﻻنتباه للدالة

بنفسها ترد بقيمتين True > False

الجمل الشرطية مادخلها

 

kenham كتب:

السكربت الذي كتبته خاطئ لست أدري من أين أحضرت المتغير a

 

و هذا هو التصحيح

def b(y):
	if any(x > y for x in[5,6,3,4]):
		return True
	return False

بالمناسبة هذا الموضوع خاص بالعودية كان عليك فتح موضوع آخر  و طرح سؤالك فيه

 

هذا المثال كتبته قبل ان اكتب المشكلة ﻻكن انا اريده في العودية !!

#20
اقتباس

 

ياخي ليست الجمل الشرطية

ارجو اﻻنتباه للدالة

بنفسها ترد بقيمتين True > False

الجمل الشرطية مادخلها

 

 

و أنا أقول لك للمرة الثانية راجع الجمل الشرطية و ستفهم

 

أنت طرحت سؤال و أنا أجبتك

 

ثق بي راجع الجمل الشرطية

if isinstance(i, list):

خرج الدالة هو (true or folse)  لكن لا تنسي أنا قبل الدالة جملة الشرطية

 

إذا كان خرج الدالة true  الجملة تنفذ و إذا كان false  الجملة لا تنفذ

#21

اشكرك جدا

#22

السلام عليكم، 

أنسب طريقة للشرح هي التفكير في المشكلة الكبيرة على أنهم مشكلة صغيرة (أبسط شئ ممكن حله)  + بعض التعقيدات
فعلى سبيل المثال مشكلة المضروب Factorial

 

939c013423574cad70f33eaa7dd68f0c.png

 

فهي معرفة كالتالي
a91da51a80ac8291d8dbcc4cb77c0936.png

أي أن المضروب = 1 في حالة كان الرقم n المطلوب حساب المضروب له = 0 (وهذه هي ابسط حالة)
وإذا كانت الرقم n أكبر من ال 0، فالناتج هو حاصل ضرب n في العدد السابق ل n وهو n-1

فالهدف من عمليات ال recursion هو تبسيط المشكلة الكبيرة مثل حساب مضروب 5 إلى حساب مضروب 0 + حساب التعقيدات في الطريق

 

>>> def factorial(n):
...     if n==0: return 1
...     else: return n*factorial(n-1)
... 
>>> factorial(0)
1
>>> factorial(1)
1
>>> factorial(2)
2
>>> factorial(5)
120
مثال اخر هو حساب طول list ما

 

>>> def length(alist):
...     if alist==[]: return 0
...     else: return 1+length(alist[1:])
... 
>>> length([])
0
>>> length([1])
1
>>> length([14,21,13])
3

 

هنا أيضا لدينا base case وهي ابسط حالة ممكن وهي ان تكون القائمة فارغة فيكون عدد عناصرها 0 
وإذا بها عناصر صارت لدينا مشكلة معقدة، نريد لحلها تحويلها للمشكلة البسيطة السهلة وهي ان تكون القائمة فارغة + بعض الحسابات في الطريق 

(map share people)

فضلا لاتقم بمراسلتي من أجل أسئلة لها أقسامها في المنتدى حتى تعم الفائدة على الجميع وللحصول على إجابات أفضل من أعضاء أكثر خبرة.
Weblog
@bitbucket
@xmonader

مواضيع مشابهة

عدد الزوار حالياً

المتواجدون خلال آخر دقيقتين · يتحدّث كل ٣٠ ثانية

—الإجمالي—أعضاء مسجّلون—زوار بدون تسجيل

جارٍ التحقق من المتواجدين…