بايثون الدوال الثابتة

مفهوم الدوال الثابتة

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

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


شروط تعريف دالة ثابتة

  • الدالة الثابتة يتم تعريفها تماماً كأي دالة عادية مع وضع الكلمة @staticmethod فوقها كمؤشر على انها دالة ثابتة.
  • يمنع وضع الكلمة self بداخلها لأن هذه الكلمة تستخدم في الأساس للوصول للمتغيرات الموضوعة كخصائص بالنسبة للكائنات التي سيتم إنشاءها من الكلاس.
  • للوصول إلى أي متغير موضوع في الكلاس من الدالة الثابتة, نكتب إسم الكلاس, ثم نضع نقطة, ثم نضع إسم المتغير.

لا تقلق إن لم تفهم كل تم ذكره حتى الآن لأنك ستفهم كل شيء لاحقاً من الأمثلة.

أمثلة شاملة

في المثال التالي قمنا بتعريف كلاس إسمه StaticExample وضعنا فيه دالة ثابتة إسمها print_msg() مهتمها فقط طباعة جملة عادية.

المثال الأول

StaticExample.py
# StaticExample هنا قمنا بتعريف الكلاس
class StaticExample:

	# هنا قمنا بتعريف دالة ثابتة في الكلاس عند إستدعائها تقوم بطباعة جملة عادية فقط
	@staticmethod
    def print_msg():
        print("Static method can be called directly from the class.")
		

Test.py
# حتى نستطيع التعامل معه StaticExample هنا قمنا بتضمين الكلاس
from StaticExample import StaticExample

# بدون الحاجة لإنشاء كائن منه StaticExample بشكل مباشر من الكلاس print_msg() هنا قمنا باستدعاء الدالة الثابتة
StaticExample.print_msg()
		

سنحصل على النتيجة التالية عند تشغيل الملف Test.

Static method can be called directly from the class.


في المثال التالي قمنا بتعريف كلاس إسمه Session وضعنا فيه 4 متغيرات ( title - language - teacher - credits ) و دالة ثابتة إسمها print_info() مهتمها فقط طباعة قيم هذه المتغيرات بطريقة مرتبة.

المثال الثاني

Session.py
# Session هنا قمنا بتعريف الكلاس
class Session:

	# هنا قمنا بوضع 4 متغيرات ( أي خصائص ) في الكلاس
    title = 'Python for beginners'
    language = 'English'
    teacher = 'Sara Smith'
    credits = 5

	# هنا قمنا بتعريف دالة ثابتة في الكلاس عند إستدعائها تقوم بطباعة قيم الخصائص بشكل مرتب
	# لاحظ أنك مجبر على وضع إسم الكلاس ثم نقطة ثم إسم المتغير الذي تريد الوصول إليه من داخل الدالة
    @staticmethod
    def print_info():
        print('Title:', Session.title)
        print('Language:', Session.language)
        print('Teacher:', Session.teacher)
        print('Credits Number:', Session.credits)
		

Test.py
# حتى نستطيع التعامل معه Session هنا قمنا بتضمين الكلاس
from Session import Session

# Session مباشرةً من الكلاس print_info() هنا قمنا باستدعاء الدالة الثابتة
Session.print_info()
		

سنحصل على النتيجة التالية عند تشغيل الملف Test.

Title: Python for beginners
Language: English
Teacher: Sara Smith
Credit Number: 5


في المثال التالي قمنا بتعريف كلاس إسمه MyTools وضعنا فيه دالة ثابتة إسمها print_words_count() الهدف منها طباعة عدد الكلمات الموجودة في النص الذي نمرره لها عند استدعائها.

المثال الثالث

MyTools.py
# MyTools هنا قمنا بتعريف الكلاس
class MyTools:

    # و تحتوي على باراميتر واحد print_words_count هنا قمنا بتعريف دالة ثابتة إسمها
    @staticmethod
    def print_words_count(val):
		# هنا قلنا إذا كانت القيمة التي مررناها لها عبارة عن قيمة نصية
        if isinstance(val, str):
			# إذا كانت هذه القيمة النصية عبارة عن نص فارغ سيتم طباعة أن النص عبارة عن نص فارغ و أن عدد الكلمات فيه هو صفر
            if val == '':
                print('Empty string, so number of words is 0')
			# و من ثم طباعة قيمته words_count إذا لم تكن هذه القيمة النصية عبارة عن نص فارغ سيتم تخزين عدد الكلمات الموجودة فيه في المتغير
            else:
                words_count = len(val.split())
                print('Number of words is:', words_count)
		# عبارة عن قيمة نصية سيتم طباعة الجملة التالية val إذا لم تكن قيمة الباراميتر
        else:
            print('Oops..', val, 'is not a string!')
		

Test.py
# حتى نستطيع التعامل معه MyTools هنا قمنا بتضمين الكلاس
from MyTools import MyTools

# هنا قمنا بتعريف متغير نصي يحتوي على مجموعة كلمات
text = 'Today, you are studying static methods.'

# text لمعرفة عدد الكلمات الموجودة في المتغير MyTools من الكلاس print_words_count() هنا قمنا باستدعاء الدالة الثابتة
MyTools.print_words_count(text)
		

سنحصل على النتيجة التالية عند تشغيل الملف Test.

Number of words is: 6


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

المثال الرابع

StaticExample.py
# StaticExample هنا قمنا بتعريف الكلاس
class StaticExample:

	# هنا قمنا بتعريف متغير ( أي خاصية ) في الكلاس و حددنا أن قيمته تساوي 5
    x = 5

    # الموجود مباشرةُ في الكلاس و ليس في كائن منه x تعرض قيمة المتغير print_x هنا قمنا بتعريف دالة ثابتة إسمها
    @staticmethod
    def print_x():
        print('StaticExample.x =', StaticExample.x)
		

Test.py
# حتى نستطيع الوصول للدالة الموجودة فيه و إنشاء كائن منه أيضاً StaticExample هنا قمنا بتضمين الكلاس
from StaticExample import StaticExample

# obj إسمه StaticExample هنا قمنا بإنشاء كائن من الكلاس
obj = StaticExample()

# من 5 إلى 10 obj الخاصة بالكائن x هنا قمنا بتغيير قيمة
obj.x = 10

# الخاصة بالكائن و التي تساوي 10 x الخاصة بالكلاس, أي 5 و ليس قيمة x لاحظ أن سيتم طباعة قيمة .obj من الكائن print_x() هنا قمنا باستدعاء الدالة الثابتة
obj.print_x()
 
# الخاصة بالكلاس x بشكل مباشر و بالتالي سيتم أيضاً طباعة قيمة StaticExample من الكلاس print_x() هنا قمنا باستدعاء الدالة الثابتة
StaticExample.print_x()    # الخاصة بالكلاس لأننا نستدعي الدالة الثابتة مباشرةً من الكلاس 

# print_x() هي إستدعاءها منه كالتالي و ليس عن طريق الدالة الثابتة obj الخاصة بالكائن x الطريقة الوحيدة لطباعة قيمة
print('obj.x =', obj.x)
		

سنحصل على النتيجة التالية عند تشغيل الملف Test.

StaticExample.x = 5
StaticExample.x = 5
obj.x = 10

الدورات

أدوات مساعدة

الأقسام

دورات
مقالات أسئلة مشاريع كتب