برمجة بايثون 2026 — جامعة هلسنكي › الجزء 3: الحلقات 3 / 15 السابق التالي

تعريف الدوال

أهداف التعلّم

بعد إتمام هذا القسم

  • ستعرف كيف تكتب دوالك الخاصة وتستدعيها
  • ستفهم ما يُقصد بالوسيط وبالمعامل في الدالة
  • ستتمكّن من تعريف المعاملات في دوالك الخاصة

معمل شيفرة بارسونز

ضمن أبحاث جارية في تعليم علوم الحاسوب في جامعة هلسنكي، يجري تطوير برمجية جديدة للتدريب على البرمجة اسمها معمل شيفرة بارسونز (Parsons Code Lab). وفي هذه البرمجية تحلّ تمارين برمجية على هيئة مسائل بارسونز، عبر ترتيب كتل الشيفرة وملئها.

بالضغط على الرابط أدناه ستحصل على مجموعة من التمارين تتيح لك مراجعة كثير من المفاهيم البرمجية الأساسية التي تعلّمتها حتى الآن: الحلقات، والجمل الشرطية، وعمليات السلاسل النصية، وما شابه. وهذه التمارين مادة اختيارية داعمة ولن تؤثر على التقييم بأي شكل. غير أن معلم الدورة يستطيع الاطلاع على إحصاءات محاولات التمارين عبر لوحة تحكم المعلم في البرمجية.

إلى التمارين

يُرجى ملاحظة أن البرمجية قيد التطوير النشط، وقد تكون هناك بعض المشكلات. يُرجى المساعدة في تطويرها عبر مشاركة أي مشكلات وملاحظات ممكنة من خلال استبيان ملاحظات مجهول الهوية! سيستغرق ملؤه نحو دقيقة واحدة، لكنه سيساعد في تطويرها مستقبلًا بما لا يُقدَّر.

شارك ملاحظاتك

قد تُستخدم نشاطات التمارين والملاحظات في الأبحاث بصيغة مجهولة الهوية تمامًا. شكرًا على مساهمتك!

تعريف الدالة

لقد استخدمنا دوال مثل len وprint وinput في برامجنا من قبل. وهذه دوال مدمجة في Python، لذا فهي دائمًا جاهزة بين يديك مهما كانت البيئة التي تبرمج فيها. لكن من الممكن أيضًا أن تُعرّف دوالك الخاصة.

قبل أن يمكن استخدام دالة، يجب أن تُعرَّف أولًا. ويبدأ أي تعريف للدالة بالكلمة المفتاحية def، وهي اختصار لكلمة تعريف (define). ثم يأتي اسم الدالة، تليه قوسان وشرطة نقطتان. وتُسمَّى هذه ترويسة (header) الدالة. وبعدها يأتي جسم (body) الدالة مُزاحًا إلى الداخل تمامًا ككتلتَي while وif.

فمثالًا، تُعرِّف الشيفرة التالية الدالة message:

def message():
    print("This is my very own function!")

إذا نُفِّذ البرنامج أعلاه فلا يبدو أن شيئًا يحدث. والسبب في ذلك أن الشيفرة الموجودة في جسم الدالة لا تُنفَّذ إلا عندما تُستدعى الدالة.

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

def message():
    print("This is my very own function!")

message()

ينتج عن ذلك أمرٌ مطبوع:

This is my very own function!

وحين تكون الدالة معرَّفة يمكن استدعاؤها عدة مرات:

def message():
    print("This is my very own function!")

message()
message()
message()
This is my very own function!
This is my very own function!
This is my very own function!

اختبار دوالك الخاصة

ملاحظة: اعتبارًا من الآن، ستطلبك معظم تمارين هذه الدورة كتابة دوالك الخاصة.

حين يتكوّن برنامج من دوال فقط، لا يبدو لتنفيذه أي أثر. والشيفرة التالية لا تطبع شيئًا، رغم أنها تحتوي على أمر طباعة:

def greet():
    print("Hi!")

سبب عدم طباعة أي شيء هو أن الشيفرة الموجودة في جسم الدالة greet لا تُنفَّذ إلا عند استدعاء الدالة.

ينبغي أن يحتوي برنامج «main» الواقع أسفل الدالة على استدعاءات دوال مناسبة، كي يمكن اختبار البرنامج. وفي الواقع، تتعامل Python مع كل شيفرة لا تقع داخل تعريفات الدوال باعتبارها جزءًا من الدالة الرئيسية (main function)، وهي التي تُنفَّذ عند تقييم الملف نفسه أو تنفيذه. فلنضف استدعاء دالة:

def greet():
    print("Hi!")

# All code not within function definitions is part of
# the main function of the program
# Calling our function:

greet()

مهم: في هذه الدورة تتطلب الاختبارات الأوتوماتيكية التي تُشغَّل على ملفات التمارين أن تكون الدالة الرئيسية فارغة. فلا ينبغي ترك أي أمر في الدالة الرئيسية ضمن حلّك. أي أن أي شيفرة تستخدمها أنت في الاختبار يجب أن تكون داخل كتلة if معرَّفة خصيصًا:

def greet():
    print("Hi!")

# Write your main function within a block like this:
if __name__ == "__main__":
    greet()

وأي شيفرة تُترك خارج الكتلة أعلاه تسبّب خطأ:

3_4_1.png

والهدف من ذلك هو التأكّد من اختبار حلّك على أرضية نظيفة، لأن الاختبارات تفحص غالبًا ما تطبعه دوالك. ومن المفيد ملاحظة أن الاختبارات لا تنفّذ أي شيفرة من داخل الكتلة if __name__ == "__main__"، لذا ينبغي ألّا تضع داخل الكتلة أي شيفرة لازمة لاستيفاء متطلّبات التمرين.

تمرين تفاعلي: الإخوة السبعة

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

Aapo
Eero
Juhani
Lauri
Simeoni
Timo
Tuomas

ملاحظة: هذا التمرين يتطلب بيئة TMC التفاعلية ولا يعمل في النسخة الثابتة.

وسائط الدالة

غالبًا ما تأخذ الدالة واحدًا أو أكثر من الوسائط (arguments)، وقد تؤثر في ما تفعله الدالة. فمثلًا، تأخذ الدالتان المدمجتان print وinput في Python النص المطلوب عرضه كوسيط:

print("Hi!")                           # argument is the string "Hi!"
name = input("What is your name? ")    # argument is the string "What is your name? "
print(name)                            # argument is the value of the variable name

سبق أن ذكرنا أن مصططلحي الوسيط (argument) و_المعامل_ (parameter) يُستعملان في الغالب للإشارة إلى الشيء نفسه. والفرق أن الوسيط يُستعمل للبيانات المُمرَّرة إلى الدالة عند استدعائها، أما داخل الدالة فتُسنَد الوسائط إلى متغيّرات تُسمّى معاملات. أي، بتقريبٍ تام، حين نستدعي الدالة نسمّي قطع البيانات المُمرَّرة وسائط، وحين نعرّف الدالة نسمّيها معاملات.

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

لنعرّف بعض الدوال التي تأخذ وسائط. وفي تعريف الدالة، تُعرَّف المعاملات بين القوسين الواقعين بعد اسم الدالة:

def hello(target):
    print("Hello", target)

استدعاء هذه الدالة مرتين، هكذا

hello("Emily")
hello("world!")

يطبع تحيّةين مختلفتين:

Hello Emily
Hello world!

فلننظر عن قرب إلى تعريف الدالة:

def hello(target):
    print("Hello", target)

في السطر الأول، أي في ترويسة الدالة، صرّحنا بأن هذه الدالة تأخذ وسيطًا وتُسنِده إلى معامل اسمُه target. وفي جسم الدالة يستخدم الأمر print القيمة المخزّنة في target.

وحين تُستدعى الدالة يحمل المعامل target القيمة المُعطاة كوسيط في استدعاء الدالة. فمثلًا، استدعاء الدالة التالي

name = "Alan"
hello(name)

يجعل المعامل target يُضبط على القيمة "Alan".

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

تمرين تفاعلي: المحرف الأول

يحتوي التمرين على الهيكل العظمي للدالة first_character. يُرجى إكماله بحيث يطبع المحرف الأول من السلسلة النصية التي تأخذها كوسيط.

def first_character(text):
     # write your code here

# testing the function:
if __name__ == "__main__":
    first_character('python')
    first_character('yellow')
    first_character('tomorrow')
    first_character('heliotrope')
    first_character('open')
    first_character('night')
p
y
t
h
o
n

ملاحظة: هذا التمرين يتطلب بيئة TMC التفاعلية ولا يعمل في النسخة الثابتة.

اختبار دوالك ذات الوسائط

كلما كانت دالتك تأخذ واحدًا أو أكثر من الوسائط، فيُستحسن أن تختبرها بوسائط مختلفة متنوعة.

وانتبه خصوصًا إلى «الحالات الخاصة» الخاصة بنوع الوسيط الذي تستخدمه. كيف تتصرّف دالتك إذا كان الوسيط صفرًا أو عددًا سالبًا، أو عددًا عشريًا بدل عدد صحيح؟ وماذا يحدث إذا كان الوسيط سلسلة نصية فارغة؟

فإذا لم تطلب منك المهمة صراحةً تضمين استدعاءات للدوال، فيجوز لك أن تضمّن استدعاءاتك الخاصة داخل كتلة if الخاصة بالدالة الرئيسية كما شُرح أعلاه. وستتجاهل الاختبارات كل ما يقع داخل كتلة if.

مزيد من الأمثلة

فلننظر إلى مزيد من أمثلة الدوال التي تأخذ وسائط. وفي تعريف الدالة التالي يكون المعامل عددًا:

def squared(x):
    print(f"The square of the number {x} is {x * x}")

squared(2)
squared(5)
The square of the number 2 is 4
The square of the number 5 is 25

وفي المقابل، يحتوي تعريف الدالة هذا على جملة if داخل جسم الدالة:

def hello(name):
    if name == "Emily":
        print("Hello", name)
    else:
        print("Hi", name)

hello("Emily")
hello("Mark")
Hello Emily
Hi Mark

تأخذ هذه الدالة وسيطين:

def sum(x, y):
    result = x + y
    print(f"The sum of the arguments {x} and {y} is {result}")

sum(1, 2)
sum(5, 24)
The sum of the arguments 1 and 2 is 3
The sum of the arguments 5 and 24 is 29

وتتضمّن الدالة أيضًا المتغيّر المساعد result، الذي تستخدمه لتخزين مجموع وسائطها.

لاحظ كيف أن أسماء المعاملات في تعريف الدالة لا علاقة لها بأي متغيّرات خارجها. فلنا نستدعي الدالة أعلاه هكذا تمامًا:

x = 100
y = 30
sum(1, 2)
sum(x + y, 10)

وهذا ينبغي أن يطبع

The sum of the arguments 1 and 2 is 3
The sum of the arguments 130 and 10 is 140

في استدعاء الدالة الأول تُسنَد إلى المعاملين القيمتان x = 1 وy = 2. وفي استدعاء الدالة الثاني تُسنَد إليهما القيمتان x = 130 وy = 10، بغضّ النظر عن المتغيّرات المسمّاة بالأسماء نفسها المستخدَمة في استدعاء الدالة.

وسنعود إلى تعريفات الدوال في بداية الجزء التالي من الدورة.

تحذير: استخدام المتغيّرات العامة داخل الدوال

في الأمثلة أعلاه رأينا أنه من الممكن إسناد متغيّرات جديدة داخل تعريفات الدوال. ويمكن للدالة أيضًا أن ترى متغيّرات مُسنَدة خارجها، في الدالة الرئيسية. وتُسمَّى هذه المتغيّرات متغيّرات عامة (global).

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

فيما يلي مثال على دالة تستخدم متغيّرًا عامًّا «من باب الخطأ»:

# this is a global variable
name = "Betty"

def hello(given_name):
    # using the global variable instead of the parameter by mistake
    print("Hello", name)

hello("Steve")
hello("Betty")
Hello Betty
Hello Betty

مهما استدعيتَ الدالة بعدد من الوسائط المختلفة، فستطبع دائمًا القيمة "Betty" المخزّنة في المتغيّر العام.

تمرين تفاعلي: المتوسط

يُرجى كتابة دالة اسمها mean، تأخذ ثلاثة وسائط صحيحة. وينبغي أن تطبع الدالة المتوسط الحسابي للوسائط الثلاثة.

mean(5, 3, 1)
mean(10, 1, 1)
3.0
4.0

ملاحظة: هذا التمرين يتطلب بيئة TMC التفاعلية ولا يعمل في النسخة الثابتة.

تمرين تفاعلي: اطبع عدّة مرّات

يُرجى كتابة دالة اسمها print_many_times(text, times)، تأخذ سلسلة نصية وعددًا صحيحًا كوسائط. ويحدد الوسيط الصحيح عدد مرّات طباعة الوسيط النصي:

print_many_times("hi", 5)

print()

text = "All Pythons, except one, grow up"
times = 3
print_many_times(text, times)
hi
hi
hi
hi
hi

All Pythons, except one, grow up.
All Pythons, except one, grow up.
All Pythons, except one, grow up.

ملاحظة: هذا التمرين يتطلب بيئة TMC التفاعلية ولا يعمل في النسخة الثابتة.

تمرين تفاعلي: مربع من محارف الشباك

يُرجى كتابة دالة اسمها hash_square(length)، تأخذ وسيطًا صحيحًا. وتطبع الدالة مربعًا من محارف الشباك، ويحدد الوسيط طول ضلع المربع.

hash_square(3)
print()
hash_square(5)
###
###
###

#####
#####
#####
#####
#####

ملاحظة: هذا التمرين يتطلب بيئة TMC التفاعلية ولا يعمل في النسخة الثابتة.

تمرين تفاعلي: رقعة شطرنج

يُرجى كتابة دالة اسمها chessboard، تطبع رقعة شطرنج مكوّنة من الآحاد والأصفار. وتأخذ الدالة وسيطًا صحيحًا يحدد طول ضلع الرقعة. راجع الأمثلة أدناه للتفاصيل:

chessboard(3)
print()
chessboard(6)
101
010
101

101010
010101
101010
010101
101010
010101

ملاحظة: هذا التمرين يتطلب بيئة TMC التفاعلية ولا يعمل في النسخة الثابتة.

تمرين تفاعلي: كلمة مربَّعة

يُرجى كتابة دالة اسمها squared، تأخذ وسيطًا من نوع سلسلة نصية ووسيطًا صحيحًا، وتطبع مربعًا من المحارف كما هو محدَّد في الأمثلة أدناه.

squared("ab", 3)
print()
squared("aybabtu", 5)
aba
bab
aba

aybab
tuayb
abtua
ybabt
uayba

ملاحظة: هذا التمرين يتطلب بيئة TMC التفاعلية ولا يعمل في النسخة الثابتة.

يُرجى الإجابة على استبيان سريع حول مادة هذا الأسبوع.

اختبار: (مكون تفاعلي غير متاح في النسخة الثابتة - ID: 4420ccdc-8422-598a-9057-89b32e8f282a)