![]() |
مجالات التسمية (namespaces) في بيثون - نسخة قابلة للطباعة +- ملتقى الواحــة (https://forums.wahaproject.org) +-- قسم : واحــة لينكس (https://forums.wahaproject.org/forum-3.html) +--- قسم : البرمجة (https://forums.wahaproject.org/forum-9.html) +--- الموضوع : مجالات التسمية (namespaces) في بيثون (/thread-112.html) |
مجالات التسمية (namespaces) في بيثون - محمد - 08-06-2018 مجالات التسمية (namespaces) في بيثون
مجال التسمية = namespace نطاق المتغير = scope محلي = local شامل = global وسيط - معطى = argument - parameter فئة = class دالة = function كتلة = block تعليمة = instruction تعبير = expression سمة = attribute معلمة = parameter مرجع = reference الدوال المتداخلة= nested functions لعل مفهوم 'نطاق المتغير' قد اعترضك سابقا، او ربما لاحظت أن متغيرين يحملان نفس الاسم متواجدان في سكربت واحد، أحدهما داخل الوحدة و الآخر داخل دالة مثلا. نجد في بيثون كما في غالب لغات البرمجة، إن لم يكن كلها، قواعد تحدد نطاق المتغير. المقصود متى وكيف يمكن الوصول الى المتغير؟ ما هي المتغيرات الممكن استخدامها داخل دالة قمنا بتعريفها؟ هل ما قمنا بتمريره اليها كوسيط؟ هل يمكننا اضافة متغيرات داخل الدالة مع امكانية الوصول اليها من خارجها؟ كود : a = 3 كود : a = 3 ## المتغيرات المحلية (local variables) يقوم بيثون بالبحث عن مرجع المتغير a في النطاق المحلي للدالة أولا. هذا النطاق يحتوي على الوسائط التي ممرناها للدالة إن وجدت، والمتغيرات التي قمنا بتعريفها داخل الدالة. في المثال الاول أعلاه، اكتشف بيثون أنه لا وجود لمتغير باسم a في النطاق المحلي للدالة، عندها مر للبحث عن a داخل نطاق محلي أشمل حيث تم تعريف الدالة، وهنا وجد a واستخدمها. في المثال الثاني، وجد بيثون المتغير a في النطاق المحلي للدالة فاستخدمها (a = 5) ، ثم لما طلبنا طباعة a مباشرة، بدأ البحث عنها في النطاق المحلي دائما، لكنه هنا النطاق الذي فيه تعريف الدالة فوجد أن a = 3 . سنقدم مزيدا من الامثلة لفهم نطاق المتغيرات أكثر: كود : def my_var(): كود : def my_var(i): ## تعميم تكون المتغيرات معزولة تماما داخل كتلة تعليمات أو داخل وحدة عبر ما يسمى 'مجال التسمية' (namespace). في بيثون مجال التسمية يجمع عددا من المتغيرات تنتمي الى كائن ما: الوحدة والدالة والفئة ومثيل الفئة كل منها تقوم بتعريف مجال تسمية خاص بها. هذا المفهوم موجود في لغات أخرى لكن بطريقة مختلفة وعادة تتطلب مجهودا اضافيا من المبرمج لعزل المتغيرات داخل مجالات تسمية. في بيثون مجرد انشائنا لوحدة جديدة يوفر مجال تسمية خاص بها وبالتالي تكون المتغيرات معزولة بمجرد كتابتنا لأول سطر كود. لنر كيف تقوم الوحدات بعزل المتغيرات عبر مجالات التسمية. سنقوم بانشاء وحدة باسم spam.py ونعرف داخلها متغيرا ودالة: كود : x = 1 # 2 كود : import spam # 2 كود : python3 eggs.py # 1 قام النظام بتخصيص مساحة من الذاكرة للكائنات ومساحة اخرى لمجالات التسمية. ما يهمنا هو المساحة المخصصة لمجالات التسمية: # 1- داخل مساحة الذاكرة المخصصة لمجالات التسمية تم تخصيص مجال تسمية للوحدة eggs # 2- عند قراءة سطر import spam خصص مجال تسمية خاص بالوحدة spam وضع فيه تعريف x و f (لكن دون تخصيص مجال تسمية للدالة f) # 3- بالنسبة للدوال سيتم انشاء مجال تسمية خاص بكل منها عند استدعائها ثم يتم استرجاعه عند الخروج من الدالة. # 4- عند قراءة السطر x = 2 قام النظام بعريف المتغير x داخل المجال المخصص لـeggs وربطه بالقيمة 2 في مساحة الذاكرة المخصصة للكائنات # 5- عند استدعاء الدالة f قام النظام بتخصيص مجال تسمية لها. داخل الدالة بحث النظام عن x في المجال المحلي للدالة لكنه لم يجده، فبحث في المجال المحلي للوحدة eggs فوجده وطبع لنا القيمة، ثم، عند الخروج من الدالة، استرجع النظام مجال التسمية الذي كان قد خصصه للدالة. # 6- عند السطر spam.f قام النظام بتخصيص مجال تسمية للدالة داخل المجال المخصص لـspam واتبع نفس المراحل، حيث بحث عن x في مجال التسمية الخاص بـf ولما لم يجده بحث عنه في المجال الأشمل اي المجال المخصص للوحدة spam وهناك وجده فطبع القيمة (1)، وعند الخروج من الدالة استرجع مساحة الذاكرة التي خصصها لها. # 7- أخيرا، عند سطر طباعة spam.x بحث النظام عن x في المجال المخصص لـspam اذا اردنا ان نلخص كل ما حدث ونعممه يمكننا ان نقول ان بيثون يبدأ البحث دائما في أقرب نطاق محلي للتعليمة ثم يتوسع تدريجيا في البحث، لذلك لا يشكل تسمية كائنات بنفس الاسم في مجالات تسمية مختلفة مشكلة بالنسبة للنظام (لكن قد يسبب مشاكل وصعوبات بالنسبة للمبرمج). من المهم أيضا أن نتذكر أننا لا نستطيع تعديل قيمة متغير (التعيين مباشرة بواسطة =) من خارج النطاق الذي تم تعريف المتغير فيه. أما بالنسبة للكائنات التي لها وظائف تسمح بتعديلها، فذلك ممكن عبر تلك الوظائف: ذلك أننا عندما نمرر كائنا كوسيط لدالة فنحن انما نمرر مرجع للكائن نفسه وليس لقيمته. بالنسبة لمن لديهم بعض المعرفة بلغات برمجة اخرى كالسي++ او الجافا، تلك اللغات تمرر افتراضيا قيمة المتغير وليس المرجع او المؤشر. كود : t = [] # قلنا أن الدالة تستطيع أن 'تقرأ' متغيرا معرفا خارجها ## المتغيرات العمومية (global variables) وفر بيثون طريقة لتعديل متغير داخل دالة إذا كان معرفا خارج نطاق الدالة. هذه الطريقة تسمى المتغيرات العمومية كود : def global_var(): كود : i = 50 قد يبدو مفهوم مجالات التسمية معقدا في البداية، وأعترف أن شرحه نظريا أصعب من تجربته عمليا، لذلك أدعو من وجد صعوبات في فهم هذا الموضوع أن يجرب أمثلة أخرى عبر البحث عن python namespace في الانترنت مثلا. |