القائمة الرئيسية

الصفحات

دورة البرمجة بلغة بايثون - الدرس التاسع (Namespace and Scope)

دورة البرمجة بلغة بايثون - الدرس التاسع (Namespace and Scope)

دورة البرمجة بلغة بايثون - الدرس التاسع (Namespace and Scope)
في هذا البرنامج التعليمي ، ستتعرف على مصطلح Namespace، والتعيين من الأسماء إلى الكائنات ، ونطاق المتغير Scope of variable.

ما هو الاسم في بايثون؟
الاسم (يسمى أيضًا المعرّف) هو ببساطة اسم يُطلق على الكائنات. كل شيء في بايثون هو كائن. الاسم هو طريقة للوصول إلى الكائن الأساسي.

على سبيل المثال ، عندما نقوم بتعيين a = 2  . فـ 2 هو كائن مخزّن في الذاكرة و a هو الاسم الذي نربطه به. يمكننا الحصول على عنوان (في ذاكرة الوصول العشوائي) لبعض الكائنات من خلال الوظيفة المضمنة ()id. دعونا نلقي نظرة على كيفية استخدامه.

# Note: You may get different values for the id

a = 2
print('id(2) =', id(2))

print('id(a) =', id(a))

الإخراج:
id(2) = 9302208
id(a) = 9302208

هنا ، يشير كلاهما إلى نفس الكائن 2 ، لذلك لديهم نفس المعرّف ()id. دعونا نجعل الأمور أكثر إثارة للاهتمام.

# Note: You may get different values for the id

a = 2
print('id(a) =', id(a))

a = a+1
print('id(a) =', id(a))

print('id(3) =', id(3))

b = 2
print('id(b) =', id(b))
print('id(2) =', id(2))

الإخراج
id(a) = 9302208
id(a) = 9302240
id(3) = 9302240
id(b) = 9302208
id(2) = 9302208

ماذا يحدث في تسلسل الخطوات أعلاه؟ لنستخدم مخططًا لشرح هذا:



مخطط الذاكرة للمتغيرات في بيثون
مخطط الذاكرة للمتغيرات في بيثون


مبدئيًا ، يتم إنشاء الكائن 2 والاسم المرتبط به ، عندما نقوم بعمل = a + 1 ، يتم إنشاء كائن جديد وهو 3 وهو الآن مرتبط بهذا الكائن.

لاحظ أن المعرف id(a والمعرف id(3 لهما نفس القيم.

علاوة على ذلك ، عندما يتم تنفيذ الامر b = 2 ، يرتبط الاسم الجديد b بالكائن السابق 2.

هذا فعال لأن بايثون لا تحتاج إلى إنشاء كائن مكرر جديد في كل مرة. هذه الطبيعة الديناميكية لربط الأسماء تجعل Python قوية ؛ يمكن أن يشير الاسم إلى أي نوع من الكائنات.

>>> a = 5
>>> a = 'Hello World!'
>>> a = [1,2,3]

كل هذه صالحة وسوف تشير إلى ثلاثة أنواع مختلفة من الكائنات في حالات مختلفة. الدوال هي كائنات أيضًا ، لذا يمكن أن يشير الاسم إليها أيضًا.

def printHello():
    print("Hello")


a = printHello

a()

الإخراج

Hello
يمكن أن يشير الاسم a نفسه إلى دالة ويمكننا استدعاء هذه الدالة باستخدام هذا الاسم.

ما هي مساحة الاسم Namespace في بايثون؟
الآن بعد أن فهمنا ما هي الأسماء ، يمكننا الانتقال إلى مفهوم مساحات الأسماء.

ببساطة ، مساحة الاسم هي مجموعة من الأسماء.

في Python ، يمكنك تخيل مساحة اسم كتعيين لكل اسم قمت بتعريفه للكائنات المقابلة.

يمكن أن تتواجد مساحات أسماء مختلفة في وقت معين ولكنها معزولة تمامًا.

يتم إنشاء مساحة اسم تحتوي على جميع الأسماء المضمنة عندما نبدأ مترجم بايثون ويكون موجودًا طالما أن المترجم يعمل.

هذا هو السبب في أن الوظائف المضمنة مثل ()id و ()print وما إلى ذلك متوفرة دائمًا من أي جزء من البرنامج. تقوم كل وحدة بإنشاء مساحة الاسم الخاصة بها.

يتم عزل مساحات الأسماء المختلفة هذه. وبالتالي ، لا يتصادم نفس الاسم الذي قد يوجد في مساحات إخرى.

يمكن أن تحتوي الوحدات على وظائف وفئات مختلفة. يتم إنشاء مساحة اسم محلية عندما يتم استدعاء دالة ، والتي تحتوي على جميع الأسماء المعرفة فيها. وبالمثل ، هو الحال مع الطبقة. قد يساعد الرسم البياني التالي في توضيح هذا المفهوم.



رسم تخطيطي لمساحات الأسماء المختلفة في Python

مساحات الأسماء المتداخلة في برمجة Python


نطاق المتغيرات في بايثون
على الرغم من تحديد العديد من مساحات الأسماء الفريدة ، فقد لا نتمكن من الوصول إليها جميعًا من كل جزء من البرنامج. يدخل مفهوم النطاق حيز التنفيذ.

النطاق هو جزء من البرنامج حيث يمكن الوصول إلى مساحة الاسم مباشرة بدون أي بادئة.

في أي لحظة ، هناك ثلاثة نطاقات متداخلة على الأقل.

  • نطاق الوظيفة الحالية التي لها أسماء محلية
  • نطاق الوحدة التي لها أسماء عامة
  • النطاق الأول الذي يحتوي على أسماء مضمنة

عند عمل مرجع داخل دالة ، يتم البحث عن الاسم في مساحة الاسم المحلية ، ثم في مساحة الاسم العامة وأخيرًا في مساحة الاسم المضمنة.

إذا كانت هناك دالة داخل دالة أخرى ، فسيتم تضمين نطاق جديد داخل النطاق المحلي.

مثال على النطاق ومساحة الاسم في بايثون

def outer_function():
    b = 20
    def inner_func():
        c = 30

a = 10
هنا ، المتغير a موجود في مساحة الاسم العمومية. المتغير b موجود في مساحة الاسم المحلية ل ()outer_function و c في مساحة الاسم المحلية لـ ()inner_function.

عندما نكون في داخل الـ ()inner_function ، تكون c هي محلية بالنسبة لنا ، b هي غير محلية و a عامة. يمكننا قراءة وتعيين قيم جديدة لـ c ولكن يمكننا فقط قراءة b و a من الدالة ()inner_function.

إذا حاولنا التعيين كقيمة لـ b ، يتم إنشاء متغير جديد b في مساحة الاسم المحلية التي تختلف عن b غير المحلية. يحدث الشيء نفسه عندما نخصص قيمة لـ a.

ومع ذلك ، إذا أعلنا أنه عام، فإن جميع المراجع والتخصيصات تذهب إلى أن تكون عامة. وبالمثل ، إذا أردنا إعادة المتغير b ، فيجب الإعلان عنه على أنه غير محلي. يوضح المثال التالي هذا الأمر.


def outer_function():
    a = 20

    def inner_function():
        a = 30
        print('a =', a)

    inner_function()
    print('a =', a)


a = 10
outer_function()
print('a =', a)

كما ترى ، ناتج هذا البرنامج هو:


a = 30
a = 20
a = 10

في هذا البرنامج ، يتم تحديد ثلاثة متغيرات مختلفة a في مساحات أسماء منفصلة ويتم الوصول إليها وفقًا لذلك. بينما في البرنامج التالي ،


def outer_function():
    global a
    a = 20

    def inner_function():
        global a
        a = 30
        print('a =', a)

    inner_function()
    print('a =', a)


a = 10
outer_function()
print('a =', a)

مخرجات البرنامج.


a = 30
a = 30
a = 30 

هنا ، جميع المراجع هي عامية بسبب استخدام الكلمة الرئيسية global.


reaction:

تعليقات