التوابع Functions في لغة البرمجة بايثون python

تعرف التوابع بأنها شيفرة برمجية على شكل كتلة منظمة وقابلة لإعادة الاستخدام وتؤن قابلية أفضل للتعديل للتطبيقات ودرجة اعلى من إعادة الاستخدام للشيفرة البرمجية.

تؤمن لغة البرمجة python العديد من التوابع القياسية كما يمكن للمستخدم إنشاء التابع الخاص به حيث يسمى هذا النوع من التوابع بـ called user-defined functions .


تعريف التابع

من الممكن تعريف التوابع لتقوم بتحقيق المطلوب وذلك وفق القواعد التالية:

  • تبدأ كتلة التابع بالكلمة المفتاحية def متبوعة باسم التابع والأقواس ( ( ) ) .
  • يجب وضع البارامترات ضمن الأقواس كما يمكن تعريف هذه البارامترات ضمن الأقواس نفسها.
  • يمكن أن تكون التعليمة الأولى في التابع تعليمة اختيارية – السلسلة التوثيقة للتابع أو docstring .
  • كتلة الشيفرة ضمن التابع تبدأ بـ (:) .
  • التعليمة التي تعيد [expression] تنهي التابع وبشكل اختياري يمكن إعادة التعبير إلى المستدعي. إن تعليمة الإعادة بدون مدخلات تماثل عدم إعادة شيء.

التركيبة البرمجية

def functionname( parameters ):

"function_docstring"

function_suite

return [expression]

بشكل افتراضي فإن البارامترات لها سلوك موضعي وعلى المستخدم إعلامها وبنفس الترتيب أنه تم إيجادها.

مثال

def printme(str):
"This prints a passed string into this function"
print str
return

استدعاء التابع

إن تعريف التابع يتضمن إعطاءه اسم محدد ويحدد البارامترات التي سوف تكون ضمن كتلة التابع والتراكيب البرمجية للشيفرة التي يمثلها التابع.
حالما يتم إنهاء التركيبة الرئيسية للتابع فإنه يمكن تنفيذه باستدعائه من تابع آخر أو مباشرة من موجه الـ python .
في المثال التالي عملية استدعاء التابع printme()

#!/usr/bin/python

# Function definition is here
def printme(str):
"This prints a passed string into this function"
print str;
return;

# Now you can call printme function
printme("I'm first call to user defined function!");
printme("Again second call to the same function");

فتظهر النتيجة التالية

I'm first call to user defined function!
Again second call to the same function

الإسناد بوجود المرجعية مقابل القيمة

يتم وضع كافة البارامترات بمرجعية خاصة بها وهذا يعني أن أي تغيير على البارامتر سينعكس على تابع الاستدعاء.

مثال

#!/usr/bin/python

# Function definition is here
def changeme(mylist):
"This changes a passed list into this function"
mylist.append([1,2,3,4]);
print"Values inside the function: ", mylist
return

# Now you can call changeme function
mylist=[10,20,30];
changeme(mylist);
print"Values outside the function: ", mylist

فتظهر النتيجة التالية

Values inside the function:[10,20,30,[1,2,3,4]]
Values outside the function:[10,20,30,[1,2,3,4]]

يوضح المثال التالي بارامتر مع مرجع والمرجع تمت كتابته ضمن تابع الاستدعاء

#!/usr/bin/python

# Function definition is here
def changeme(mylist):
"This changes a passed list into this function"
mylist=[1,2,3,4]; # This would assig new reference in mylist
print"Values inside the function: ", mylist
return

# Now you can call changeme function
mylist=[10,20,30];
changeme(mylist);
print"Values outside the function: ", mylist

البارامتر mylist محلي بالنسبة لتغيير التابع وتغيير هذا البارامتر ضمن التابع لا يغير من mylist عندها لا ينفذ التابع شيئاً وفي النهاية تظهر النتيجة التالية:

Values inside the function:[1,2,3,4]
Values outside the function:[10,20,30]

مدخلات التوابع

يمكن استدعاء التابع باستخدام أي من المدخلات التالية:

  • المدخلات المطلوبة.
  • المدخلات المفتاحية.
  • المدخلات الافتراضية.
  • المدخلات من النوع طول – متحول.

المدخلات المطلوبة

وهي المدخلات التي تسند إلى التابع وفق ترتيب مكاني صحيح. هنا عدد المدخلات في تابع الاستدعاء والتي يجب أن تكون مرتبطة تماماً مع تعريف التابع.
لاستدعاء التابع printme() يجب إسناد مدخل واحد وإلا يعطي خطأً برمجياً كالتالي:

#!/usr/bin/python

# Function definition is here
def printme( str ):
"This prints a passed string into this function"
print str;
return;

# Now you can call printme function
printme();

فتظهر النتيجة التالية

Traceback (most recent call last):
File"test.py", line 11, in<module>
printme();
TypeError: printme() takes exactly 1 argument (0 given)

المدخلات المفتاحية

هذه المدخلات مرتبطة مع استدعاء التابع. عندما يتم استخدام المدخلات المفتاحية في استدعاء التابع فإن المستدعي يعرف المدخلات وفق اسم المعامل.
يسمح هذا للمستخدم بإلغاء المدخلات أو وضعها خارج الترتيب لأن المترجم بإمكانه استخدام الكلمات المفتاحية للربط بين القيم والمعاملات.
يمكن أيضاً استدعاء الكلمة المفتاحية للتابع printme() بالطرق التالية:

#!/usr/bin/python

# Function definition is here
def printme(str):
"This prints a passed string into this function"
print str;
return;

# Now you can call printme function
printme(str="My string");

فتظهر النتيجة التالية

Mystring

يعطي المثال التالي صورة أوضح ويلاحظ عدم أهمية ترتيب المعاملات

#!/usr/bin/python

# Function definition is here
def printinfo( name, age ):
"This prints a passed info into this function"
print"Name: ", name;
print"Age ", age;
return;

# Now you can call printinfo function
printinfo( age=50, name="miki");

فتظهر النتيجة التالية

Name:miki
Age50

المدخلات الافتراضية

تفترض هذه المدخلات أن القيمة الافتراضية 0 إذا لم يتم تحديد القيمة عند استدعاء التابع. يطبع العمر الافتراضي إذا لم يكن محدداً

#!/usr/bin/python
# Function definition is here
def printinfo( name, age =35):
"This prints a passed info into this function"
print"Name: ", name;
print"Age ", age;
return;

# Now you can call printinfo function
printinfo( age=50, name="miki");
printinfo( name="miki");

فتظهر النتيجة التالية

Name:miki
Age50
Name:miki
Age35

المدخلات من النوع طول – متحول

من الممكن أن يضطر المستخدم لمعالجة التابع من أجل مدخلات عديدة أكثر من تلك المحددة عند تعريف التابع حيث تسمى هذه المدخلات بالمدخلات من النوع طول – متحول ولم يتم تسميتها في تعريف التابع بعكس المدخلات الافتراضية والمدخلات المطلوبة.

التركيبة البرمجية لتابع مع مدخلات لا تحوي كلمات مفتاحية-

def functionname([formal_args,] *var_args_tuple):
"function_docstring"
function_suite
return[expression]

تتوضع الإشارة (*) قبل اسم المتحول الذي يضبط قيم جميع مدخلات المتحول. يبقى هذا الصف فارغاً إذا لم يتم تحديد مدخلات إضافية خلال


عملية استدعاء التابع

مثال

#!/usr/bin/python

# Function definition is here
def printinfo( arg1,*vartuple):
"This prints a variable passed arguments"
print"Output is: "
print arg1
for var in vartuple:
print var
return;

# Now you can call printinfo function
printinfo(10);
printinfo(70,60,50);

فتظهر النتيجة التالية

Outputis:
10
Outputis:
70
60
50

التوابع المجهولة

سميت هذه التوابع بهذا الاسم لأنه لم يعلن عنها بأسلوب معياري باستخدام المفتاح defويمكن استخدام الكلمة المفتاحية lambdaلإنشاء توابع مجهولة صغيرة.

  1. – يمكن ان تأخذ الصيغة Lambda أي عدد من المدخلات ولكن تعيد قيمة واحدة فقط على شكل تعبير ولا يمكن أن تحتوي على اوامر أو تعابير متعددة.
  2. – لا يمكن أن يتم استدعاء التابع المجهول بشكل مباشر لأن الكلمة المفتاحية lambda يتطلب تعبيراً.
  3. – إن التوابع Lambda لها الفراغات الخاصة بأسمائها ولا يمكن إسناد متحولات جديدة غير الموجودة في قائمة البارامترات.
  4. – مع أن الـ Lambda تبدو على أنها تعليمة بسطر واحد إلا أنها لا تشبه التعليمات ذات السطر الواحد في لغات البرمجة C و C++.

التركيبة البرمجية

lambda[arg1 [,arg2,.....argn]]:expression

يوضح المثال التالي كيفية عمل الـ lambda

#!/usr/bin/python

# Function definition is here
sum =lambda arg1, arg2: arg1 + arg2;

# Now you can call sum as a function
print"Value of total : ", sum(10,20)
print"Value of total : ", sum(20,20)

فتظهر النتيجة التالية

Value of total :30
Value of total :40

التعليمة return

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

#!/usr/bin/python

# Function definition is here
def sum( arg1, arg2 ):
# Add both the parameters and return them."
total = arg1 + arg2
print"Inside the function : ", total
return total;

# Now you can call sum function
total = sum(10,20);
print"Outside the function : ", total

فتظهر النتيجة التالية

Inside the function:30
Outside the function:30

مجال المتحولات

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

هناك مجالان أساسيان للمتحولات في لغة البرمجة python –

  • المتحولات العامة.
  • المتحولات الموضعية (المحلية).

المتحولات العامة مقابل الموضعية

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

مثال

#!/usr/bin/python

total =0; # This is global variable.
# Function definition is here
def sum( arg1, arg2 ):
# Add both the parameters and return them."
total = arg1 + arg2; # Here total is local variable.
print"Inside the function local total : ", total
return total;

# Now you can call sum function
sum(10,20);
print"Outside the function global total : ", total

فتظهر النتيجة التالية

Inside the functionlocal total :30
Outside the functionglobal total :0