الدوال في بايثون: شرح عملي مبسّط مع أمثلة برمجية
تُعدّ الدوال في لغة Python من أهم الأدوات التي تساعد على كتابة كود منظم وقابل لإعادة الاستخدام. فبدلاً من تكرار نفس التعليمات في أكثر من موضع، يمكنك وضعها داخل دالة واحدة ثم استدعاؤها كلما احتجت إليها. هذه الفكرة لا تجعل الكود أقصر فحسب، بل تسهّل أيضاً صيانته وفهمه وتطويره لاحقاً.
إذا كنت قد بدأت تعلم Python من قبل، فمن المؤكد أنك استخدمت دوال جاهزة مثل print() لعرض النصوص وinput() لقراءة البيانات من المستخدم. في هذه الحالة، أنت تستفيد من الدالة دون الحاجة إلى معرفة كيفية بنائها داخلياً، وهذا ما يُعرف في البرمجة بمفهوم abstraction أو التجريد.
في هذا المقال، سنتعلم كيفية إنشاء الدوال المعرّفة من قبل المستخدم في Python، وكيفية تمرير الوسائط إليها، واستخدام القيم الافتراضية، وإرجاع قيمة واحدة أو عدة قيم، بالإضافة إلى التعامل مع عدد متغير من الوسائط.
ما هي الدوال في بايثون ولماذا نستخدمها؟
الدالة هي كتلة من الأوامر البرمجية تُنفَّذ عند استدعائها. الهدف الأساسي منها هو:
- تقليل تكرار الكود.
- تنظيم المنطق البرمجي في أجزاء واضحة.
- تسهيل اختبار الكود وصيانته.
- جعل البرامج أكثر قابلية للتوسّع.
عندما يكون لديك إجراء يتكرر كثيراً، مثل التحقق من قيمة، أو تنسيق نص، أو إجراء عملية حسابية، فمن الأفضل تحويله إلى دالة بدل إعادة كتابة نفس التعليمات كل مرة.
صياغة الدالة في Python
لإنشاء دالة جديدة، نستخدم الكلمة المفتاحية def متبوعة باسم الدالة، ثم أقواس تحتوي على المعاملات إن وُجدت، وبعدها النقطتان الرأسيتان :.
def function_name(parameters):
# What the function does goes here
return result
تتكون الدالة عادة من العناصر التالية:
def: الكلمة المستخدمة لتعريف الدالة.- اسم الدالة: ويفضل أن يكون واضحاً ويعبّر عن وظيفتها.
- المعاملات
parameters: وهي المدخلات التي تستقبلها الدالة. - جسم الدالة: وهو الجزء المزاح إلى الداخل
indentationويحتوي على التعليمات. - جملة
return: تُستخدم لإرجاع ناتج من الدالة، وهي اختيارية.
من المهم التفريق بين parameters وarguments:
parameters: الأسماء المكتوبة داخل تعريف الدالة.arguments: القيم الفعلية التي نرسلها عند استدعاء الدالة.
كيفية إنشاء دالة بسيطة في بايثون
لنبدأ بمثال سهل لدالة لا تستقبل أي وسائط ولا تُرجع أي قيمة، بل تطبع رسالة ترحيبية فقط.
def my_func():
print("Hello! Hope you're doing well")
هذه الدالة اسمها my_func()، وعند استدعائها ستعرض الرسالة المحددة. لكن تعريف الدالة وحده لا يكفي، إذ لن يحدث شيء حتى تقوم باستدعائها بشكل صريح.
my_func()
# Output
# Hello! Hope you're doing well
متى نستخدم هذا النوع من الدوال؟
يُستخدم هذا النوع عندما تريد تنفيذ إجراء محدد لا يحتاج إلى مدخلات، مثل عرض رسالة، تهيئة إعدادات، أو طباعة معلومات ثابتة.
إنشاء دالة تستقبل وسائط
في التطبيقات العملية، غالباً ما تحتاج الدالة إلى بيانات تعمل عليها. هنا يأتي دور الوسائط.
def my_func(name, place):
print(f"Hello {name}! Are you from {place}?")
عند استدعاء هذه الدالة، يجب تمرير قيمتين: الأولى للاسم name والثانية للمكان place.
my_func("Jane", "Paris")
# Output
# Hello Jane! Are you from Paris?
الوسائط الموضعية Positional Arguments
إذا مرّرت القيم بترتيب خاطئ، فستصل إلى المعاملات بشكل غير صحيح:
my_func("Hawaii", "Robert")
# Output
# Hello Hawaii! Are you from Robert?
السبب هنا أن Python تتعامل مع هذه القيم على أنها وسائط موضعية، أي أن أول قيمة تُرسَل لأول معامل، وثاني قيمة تُرسَل للثاني، وهكذا.
الوسائط المسماة Keyword Arguments
لحل مشكلة الترتيب، يمكنك إرسال القيم باستخدام أسماء المعاملات:
my_func(place="Hawaii", name="Robert")
# Output
# Hello Robert! Are you from Hawaii?
في هذه الحالة، لا يهم ترتيب القيم ما دامت أسماء المعاملات صحيحة. هذه الطريقة مفيدة جداً عندما تحتوي الدالة على أكثر من وسيط، وتريد أن تجعل الاستدعاء أوضح وأسهل قراءة.
الدوال ذات الوسائط الافتراضية في بايثون
أحياناً يكون هناك وسيط يأخذ نفس القيمة في معظم الاستدعاءات. بدلاً من تكرار هذه القيمة كل مرة، يمكن تعيين قيمة افتراضية له داخل تعريف الدالة.
لننشئ دالة تحسب إجمالي المبلغ الواجب دفعه في مطعم بناءً على قيمة الفاتورة ونسبة الإكرامية:
def total_calc(bill_amount, tip_perc=10):
total = bill_amount * (1 + 0.01 * tip_perc)
total = round(total, 2)
print(f"Please pay $ {total}")
في هذا المثال، الوسيط tip_perc لديه قيمة افتراضية تساوي 10. إذا لم يمرر المستخدم قيمة مختلفة، فسيتم استخدام هذه القيمة تلقائياً.
# specify only bill_amount
# default value of tip percentage is used
total_calc(150)
# Output
# Please pay $ 165.0
# specify both bill_amount and a custom tip percentage
# the tip percentage specified in the function call is used
total_calc(200, 15)
# Output
# Please pay $ 230.0
total_calc(167, 7.5)
# Output
# Please pay $ 179.53
متى تكون القيم الافتراضية مفيدة؟
- عندما يكون هناك سلوك شائع تريد اعتماده تلقائياً.
- عندما ترغب في جعل استدعاء الدالة أبسط.
- عندما تريد توفير مرونة دون إجبار المستخدم على تمرير كل القيم في كل مرة.
كيفية إنشاء دالة تُرجع قيمة
حتى الآن رأينا دوالاً تطبع نتائج فقط. لكن في كثير من الحالات، يكون من الأفضل أن تُرجع الدالة قيمة حتى نستخدمها لاحقاً في متغيرات أو عمليات أخرى.
لنكتب دالة تحسب حجم متوازي المستطيلات بالاعتماد على الطول والعرض والارتفاع:
def volume_of_cuboid(length, breadth, height):
return length * breadth * height
تقوم جملة return بإرجاع الناتج إلى المكان الذي استُدعيت منه الدالة.
volume = volume_of_cuboid(5.5, 20, 6)
print(f"Volume of the cuboid is {volume} cubic units")
# Output
# Volume of the cuboid is 660.0 cubic units
الفرق بين print() وreturn
print()تعرض القيمة فقط على الشاشة.returnتُعيد القيمة لكي تُستخدم لاحقاً داخل البرنامج.
ولهذا السبب، تكون return أكثر عملية عند بناء برامج حقيقية أو دوال قابلة لإعادة الاستخدام.
كيفية إرجاع عدة قيم من الدالة
في Python، يمكن للدالة أن تُرجع أكثر من قيمة في سطر واحد. عملياً، تُعاد هذه القيم على هيئة tuple.
لننشئ دالة تحسب حجم المكعب ومساحة سطحه الكلية اعتماداً على طول الضلع:
def cube(side):
volume = side ** 3
surface_area = 6 * (side ** 2)
return volume, surface_area
إذا خزّنت الناتج في متغير واحد، فستحصل على tuple:
returned_values = cube(8)
print(returned_values)
# Output
# (512, 384)
ويمكنك أيضاً فك هذا tuple إلى متغيرين منفصلين:
volume, area = cube(6.5)
print(f"Volume of the cube is {volume} cubic units and the total surface area is {area} sq. units")
# Output
# Volume of the cube is 274.625 cubic units and the total surface area is 253.5 sq. units
فائدة إرجاع عدة قيم
هذا الأسلوب مفيد عندما تكون النتائج مرتبطة ببعضها، مثل إرجاع الطول والعرض، أو الحالة والرسالة، أو القيمة والمؤشر المرافق لها.
إنشاء دالة تقبل عدداً متغيراً من الوسائط
أحياناً لا تعرف مسبقاً عدد القيم التي سيرسلها المستخدم إلى الدالة. هنا يمكن استخدام *args لاستقبال عدد غير محدد من الوسائط.
def my_var_sum(*args):
sum = 0
for arg in args:
sum += arg
return sum
داخل هذه الدالة، يتم التعامل مع args كأنه مجموعة من القيم يمكن المرور عليها باستخدام حلقة for.
# Example 1 with 4 numbers
sum = my_var_sum(99, 10, 54, 23)
print(f"The numbers that you have add up to {sum}")
# Output
# The numbers that you have add up to 186
# Example 2 with 3 numbers
sum = my_var_sum(9, 87, 45)
print(f"The numbers that you have add up to {sum}")
# Output
# The numbers that you have add up to 141
# Example 3 with 6 numbers
sum = my_var_sum(5, 21, 36, 79, 45, 65)
print(f"The numbers that you have add up to {sum}")
# Output
# The numbers that you have add up to 251
متى نستخدم *args؟
- عندما يكون عدد المدخلات غير ثابت.
- عندما تريد مرونة أكبر في استدعاء الدالة.
- عند بناء أدوات عامة، مثل دوال الجمع أو التنسيق أو الدمج.
أفضل ممارسات كتابة الدوال في بايثون
لتحسين جودة الكود وجعل الدوال أكثر احترافية، احرص على النقاط التالية:
- اختر أسماء واضحة ومعبرة للدوال مثل
calculate_total()بدلاً من أسماء غامضة. - اجعل كل دالة تؤدي مهمة واحدة فقط قدر الإمكان.
- استخدم
returnعندما تحتاج إلى إعادة استخدام النتيجة لاحقاً. - قلّل عدد الوسائط ما أمكن لتبسيط الاستدعاء.
- استخدم الوسائط المسماة عندما يكون ذلك أوضح للقارئ.
- أضف تعليقات أو توثيقاً مختصراً إذا كانت الدالة تنفذ منطقاً غير بديهي.
ملخص سريع لما تعلمناه
بعد هذا الشرح، أصبحت لديك صورة أوضح عن أساسيات الدوال في Python. لقد تعرّفنا على:
- كيفية تعريف دالة باستخدام
def. - كيفية استدعاء الدالة وتمرير الوسائط إليها.
- الفرق بين الوسائط الموضعية والوسائط المسماة.
- استخدام القيم الافتراضية لتبسيط الاستدعاء.
- إرجاع قيمة واحدة أو عدة قيم باستخدام
return. - إنشاء دوال تتعامل مع عدد متغير من الوسائط باستخدام
*args.
الخلاصة التقنية
إتقان الدوال في Python ليس مجرد خطوة تعليمية للمبتدئين، بل هو أساس حقيقي لكتابة كود احترافي قابل للتطوير. كلما أحسنت تقسيم برنامجك إلى دوال صغيرة وواضحة، أصبح الكود أسهل في القراءة والاختبار وإعادة الاستخدام. لذلك، إذا كنت تسعى إلى تحسين مستواك البرمجي، فابدأ من الدوال: تعلّم كيف تبنيها، ومتى تستخدم return، وكيف تصمم وسائطها بذكاء.