|
1 | 1 | .. role:: emoji-size |
2 | 2 |
|
3 | 3 | .. meta:: |
4 | | - :description: کتاب آموزش زبان برنامه نویسی پایتون به فارسی، آموزش شی گرایی در پایتون، معرفی رابطه های وراثت (Inheritance) و انجمن (Association) در پایان، OOP در پایتون |
| 4 | + :description: کتاب آموزش زبان برنامه نویسی پایتون به فارسی، آموزش شی گرایی در پایتون، معرفی رابطه های وراثت (Inheritance) و انجمن (Association) در پایان، OOP در پایتون، ترکیب در پایتون، Method Resolution Order یا MRO پایتون، Composition و Aggregation در پایتون، وراثت چندگانه در پایتون، Multiple Inheritance پایتون |
5 | 5 | :keywords: آموزش, آموزش پایتون, آموزش برنامه نویسی, پایتون, تابع, کتابخانه, پایتون, شی گرایی در پایتون |
6 | 6 |
|
7 | 7 |
|
|
262 | 262 | True |
263 | 263 | >>> isinstance(sub, SuperClass) |
264 | 264 | True |
| 265 | + >>> isinstance(sub, object) |
| 266 | + True |
| 267 | + |
| 268 | + در واقع این نمایش رابطه **IS-A** میباشد. توجه داشته باشید که این رابطه از پایین به بالا میباشد و برعکس آن صادق نیست. برای نمونه، مثال نخست را بیاد آورید. گنجشک (Sparrow) یک Animal است ولی Animal لزوما گنجشک نیست! |
| 269 | + |
| 270 | + تمام کلاسهای پایتون به صورت ضمنی از کلاس ``object`` ارثبری دارند. |
| 271 | + |
| 272 | + |
| 273 | + |
265 | 274 |
|
266 | 275 |
|
267 | 276 | وراثت چندگانه (Multiple Inheritance) |
|
293 | 302 | >>> isinstance(sub, SuperClassB) |
294 | 303 | True |
295 | 304 | >>> isinstance(sub, SuperClassC) |
| 305 | + True |
| 306 | + >>> isinstance(sub, object) |
296 | 307 | True |
297 | 308 |
|
298 | 309 | نمونه کد بالا نمایش ساختار وراثت چندگانه در پایتون است که در آن کلاس SubClass به ترتیب از سه کلاس SuperClassA و SuperClassB و SuperClassC ارثبری دارد. |
299 | 310 |
|
300 | | -اکنون مهمترین چالش چگونگی دسترسی به متدهای هر یک از این superclassها میباشد. تاکنون برای دسترسی به متدهای superclass از تابع ``super`` استفاده میکردیم ولی حالا که صحبت از چندین superclass است، مثلا مقدارهی متد ``__init__`` توسط این تابع چگونه میتواند انجام شود؟ چگونه باید به پایتون بگوییم آرگومانهایی را که میخواهیم دقیقا به متد خاصی از superclass مورد نظر ارسال کند؟ البته نگران نباشید، پایتون مشکلی نخواهد داشت. در ادامه، حالات مختلف حل این مسئله را بررسی خواهیم کرد. |
| 311 | +اکنون مهمترین چالش چگونگی دسترسی به متدهای هر یک از این superclassها میباشد. تاکنون برای دسترسی به متدهای superclass از تابع ``super`` استفاده میکردیم ولی حالا که صحبت از چندین superclass است، مثلا مقدارهی متد ``__init__`` (که در تمام superclassها با همین نام وجود دارد) توسط این تابع چگونه میتواند انجام شود؟ چگونه باید به پایتون بگوییم آرگومانهایی را که میخواهیم دقیقا به متد خاصی از superclass مورد نظر ارسال کند؟ البته نگران نباشید، پایتون مشکلی نخواهد داشت. در ادامه، حالات مختلف حل این مسئله را بررسی خواهیم کرد. |
301 | 312 |
|
302 | 313 | **شیوه یکم:** خیلی ساده، میتوانیم اصلا از تابع ``super`` استفاده نکنیم و متدهای هر superclass را مستقیم با نام خودش فراخوانی کنیم که البته در این روش لازم است به ازای تمام پارامترهای متد superclass آرگومان متناظر را ارسال نماییم، از جمله برای ``self``: |
303 | 314 |
|
|
406 | 417 |
|
407 | 418 | متدها در کلاس از قوانین حاکم بر تابع در پایتون پیروی میکنند، در نتیجه متدهای متناظر در superclassها باید به گونهای تعریف شده باشند که هر تعداد پارامتر را بپذیرند. برای این منظور در انتهای تعریف پارامترهای این متدها، یک پارامتر ``args*`` قرار دادهایم. این پارامتر، تمامی آرگومانهای اضافی ارسال شده به آن تابع را در خود نگهداری میکند. در نتیجه برای ادامه روند فراخوانی متدهای نظیر باقیمانده، تنها کافی است این مقدار ارسال گردد. (تابع در پایتون - درس دوازدهم) |
408 | 419 |
|
409 | | -اگر شیوه ارسال آرگومانها را به صورت **نام=مقدار** تغییر دهیم، ترتیب ارسال آرگومانها از اهمیت میافتد و پیادهسازی آسانتر و کد خواناتر خواهد بود: |
| 420 | + |
| 421 | + |
| 422 | +اگر شیوه ارسال آرگومانها را به صورت **نام=مقدار** تغییر دهیم، ترتیب ارسال آرگومانها از اهمیت میافتد و پیادهسازی آسانتر و کد خواناتر خواهد بود - با این روش چنانچه متدهای مورد نظر در superclasها پارامتر همنام نداشته باشند، حتی ترتیب MRO نیز دیگر اهمیت نخواهد داشت: |
410 | 423 |
|
411 | 424 | .. code-block:: python |
412 | 425 | :linenos: |
@@ -471,7 +484,7 @@ Method Resolution Order |
471 | 484 | (<class '__main__.C'>, <class '__main__.B'>, <class '__main__.A'>, <class 'object'>) |
472 | 485 |
|
473 | 486 |
|
474 | | -۳) محاسبه حاصل الگوریتم C3 linearization برای یک کلاس که بیش از یک سطح سلسله مراتب وراثت دارد کمی زحمت دارد! در حالت کلی این مقدار برابر است با: «لیستی تک عضوی شامل آن کلاس » ``+`` لیستی با اعضای منحصر به فرد که حاصل ادغام (merge) «نتیجه خطی شدن (linearization) superclassهای آن کلاس» و «لیستی از superclassهای آن کلاس». عمل ادغام در اینجا علاوه بر اینکه تکرارپذیر میباشد نکاتی دارد که در ادامه ذکر خواهد شد . |
| 487 | +۳) محاسبه حاصل الگوریتم C3 linearization برای یک کلاس که بیش از یک سطح سلسله مراتب وراثت دارد کمی زحمت دارد! در حالت کلی این مقدار برابر است با: «لیستی تک عضوی شامل آن کلاس » ``+`` لیستی با اعضای منحصر به فرد که حاصل ادغام (merge) «نتیجه خطی شدن (linearization) تک تک superclassهای آن کلاس» و «لیستی از superclassهای آن کلاس». عمل ادغام در اینجا علاوه بر اینکه تکرارپذیر میباشد نکاتی دارد که در ادامه ذکر خواهد شد . |
475 | 488 |
|
476 | 489 | اکنون برای پی بردن به چگونگی ایجاد حاصل ``__Class.__mro`` و درک عملکرد الگوریتم C3 linearization دو مثال معروف در این زمینه را بررسی خواهیم کرد. نخست ساختار الماس (Diamond): |
477 | 490 |
|
@@ -514,25 +527,25 @@ Method Resolution Order |
514 | 527 | = [D, B, C, A] |
515 | 528 |
|
516 | 529 |
|
517 | | -* سطر ۱: حاصل خطی سازی (linearization) کلاس A یا همان L(A) برابر است با لیستی که تنها شامل همان کلاس A است چرا که کلاس A بدون superclass است. |
| 530 | +* **سطر ۱:** حاصل خطی سازی (linearization) کلاس A یا همان L(A) برابر است با لیستی که تنها شامل همان کلاس A است چرا که کلاس A بدون superclass است. |
518 | 531 |
|
519 | | -* سطر ۳: حاصل خطی سازی (linearization) کلاس B یا همان L(B) برابر است با «لیستی که تنها شامل همان کلاس B» ``+`` ادغام «حاصل خطی سازی (linearization) تک تک superclassهای کلاس B - در اینجا: L(A)» و لیستی از superclassهای کلاس B - در اینجا: [A] |
| 532 | +* **سطر ۳:** حاصل خطی سازی (linearization) کلاس B یا همان L(B) برابر است با «لیستی که تنها شامل همان کلاس B» ``+`` ادغام «حاصل خطی سازی (linearization) تک تک superclassهای کلاس B - در اینجا: L(A)» و لیستی از superclassهای کلاس B - در اینجا: [A] |
520 | 533 |
|
521 | | -* سطر۴: حاصل L(A) جایگذاری شده است. |
| 534 | +* **سطر ۴:** حاصل L(A) جایگذاری شده است. |
522 | 535 |
|
523 | | -* سطر ۵: حاصل ادغام چند لیست که تنها شامل یک کلاس میباشند برابر است با آن کلاس: ``[A] + [B] = [B,A]`` |
| 536 | +* **سطر ۵:** حاصل ادغام چند لیست که تنها شامل یک کلاس میباشند برابر است با آن کلاس: ``[A] + [B] = [B,A]`` |
524 | 537 |
|
525 | | -* سطر ۷: حاصل خطی سازی (linearization) کلاس C همانند کلاس B میباشد. |
| 538 | +* **سطر ۷:** حاصل خطی سازی (linearization) کلاس C همانند کلاس B میباشد. |
526 | 539 |
|
527 | | -* سطر ۱۱: حاصل خطی سازی (linearization) کلاس D یا همان L(D) برابر است با «لیستی که تنها شامل همان کلاس D» ``+`` ادغام «حاصل خطی سازی (linearization) تک تک superclassهای کلاس D با حفظ ترتیب از چپ به راست - در اینجا: L(B) , L(C)» و لیستی از superclassهای کلاس D با حفظ ترتیب از چپ به راست - در اینجا: [B,C] |
| 540 | +* **سطر ۱۱:** حاصل خطی سازی (linearization) کلاس D یا همان L(D) برابر است با «لیستی که تنها شامل همان کلاس D» ``+`` ادغام «حاصل خطی سازی (linearization) تک تک superclassهای کلاس D با حفظ ترتیب از چپ به راست - در اینجا: L(B) , L(C)» و لیستی از superclassهای کلاس D با حفظ ترتیب از چپ به راست - در اینجا: [B,C] |
528 | 541 |
|
529 | | -* سطر ۱۲: حاصل L(B) و L(C) جایگذاری شده است. |
| 542 | +* **سطر ۱۲:** حاصل L(B) و L(C) جایگذاری شده است. |
530 | 543 |
|
531 | | -* سطر ۱۳: اکنون عملیات ادغام شامل بیش از یک کلاس است، در این شرایط عملیات ادغام و انتخاب یک کلاس مطلوب آنقدر تکرار میشود تا دیگر کلاسی باقی نماند. فرآیند انتخاب کلاس مطلوب به این صورت است که از چپترین کلاس موجود در چپترین لیست شروع میکنیم به انتخاب، این کلاس میبایست در باقی لیستها در صورت وجود چپترین عضو باشد، در غیر این صورت چپترین کلاس موجود در لیست بعدی انتخاب و بررسی خواهد شد. چنانچه کلاس انتخاب شده شرایط را دارا باشد عمل ادغام برای آن کلاس صورت میپذیرد و داخل تمام لیستها در صورت وجود نیز حذف میگردد. در اینجا: ابتدا کلاس B انتخاب میشود، این کلاس شرایط مطلوب بودن را دارا میباشد، در نتیجه عمل ادغام برای آن به انجام میرسد. |
| 544 | +* **سطر ۱۳:** اکنون عملیات ادغام شامل بیش از یک کلاس است، در این شرایط عملیات ادغام و انتخاب یک کلاس مطلوب آنقدر تکرار میشود تا دیگر کلاسی باقی نماند. فرآیند انتخاب کلاس مطلوب به این صورت است که از چپترین کلاس موجود در چپترین لیست شروع میکنیم به انتخاب، این کلاس میبایست در باقی لیستها در صورت وجود چپترین عضو باشد، در غیر این صورت چپترین کلاس موجود در لیست بعدی انتخاب و بررسی خواهد شد. چنانچه کلاس انتخاب شده شرایط را دارا باشد عمل ادغام برای آن کلاس صورت میپذیرد و داخل تمام لیستها در صورت وجود نیز حذف میگردد. در اینجا: ابتدا کلاس B انتخاب میشود، این کلاس شرایط مطلوب بودن را دارا میباشد، در نتیجه عمل ادغام برای آن به انجام میرسد. |
532 | 545 |
|
533 | | -* سطر ۱۴: در ادامه عمل ادغام فرآیند خطی سازی برای کلاس D، این بار ابتدا کلاس A انتخاب میشود، این کلاس شرایط لازم را ندارد چرا که در جایگاهی از لیست دوم نیز حضور دارد که جایگاه نخست (چپترین) نیست. کلاس A رها میشود و به سراغ لیست دوم میرویم، نخستین عضو آن یعنی کلاس C شرایط لازم برای ادغام را دارد، در نتیجه در این مرحله عمل ادغام برای کلاس C به انجام میرسد. |
| 546 | +* **سطر ۱۴:** در ادامه عمل ادغام فرآیند خطی سازی برای کلاس D، این بار ابتدا کلاس A انتخاب میشود، این کلاس شرایط لازم را ندارد چرا که در جایگاهی از لیست دوم نیز حضور دارد که جایگاه نخست (چپترین) نیست. کلاس A رها میشود و به سراغ لیست دوم میرویم، نخستین عضو آن یعنی کلاس C شرایط لازم برای ادغام را دارد، در نتیجه در این مرحله عمل ادغام برای کلاس C به انجام میرسد. |
534 | 547 |
|
535 | | -* سطر ۱۵: حاصل ادغام چند لیست که تنها شامل یک کلاس میباشند برابر است با همان کلاس، در نتیجه کلاس A انتخاب و عمل ادغام برای آن به انجام میرسد. |
| 548 | +* **سطر ۱۵:** حاصل ادغام چند لیست که تنها شامل یک کلاس میباشند برابر است با همان کلاس، در نتیجه کلاس A انتخاب و عمل ادغام برای آن به انجام میرسد. |
536 | 549 |
|
537 | 550 | عملیات با موفقیت به پایان رسید و ما به مقداری برابر با ``__D.__mro`` دست پیدا کردیم! |
538 | 551 |
|
|
0 commit comments