شكلان لاستدعاء الإجراء

وقد وضعت اللغات الكائنية (Object-oriented) مثل بايثون صياغة خاصَّةً: للإجراء المسند إلى الكائن. وبذلك يتحصل لدينا طريقتان كلتاهما تؤديان نفس المعنى:

  1. إسناد الإجراء للنوع: list.append(xs, 25)
  2. إسناد الإجراء للكائن: xs.append(25)

ومثاله أيضًا في الإجراء list.sort للترتيب وكذلك في list.append للإضافة:

xs = [20, 10, 30, 40]
ys = [20, 10, 30, 40]
list.sort(xs)
ys.sort()
print(xs == ys)
list.append(xs, 50)
ys.append(50)
print(xs == ys)

نتيجة الإجراء

لابد للإجراء -حتى يكون نافعًا- أن يكون له أثر. وإنما يحقق الإجراء تأثيرًا بإحدى طريقتين:

أحدها: الرجوع بنتيجة لموضِع الاستدعاء؛ وذلك بجملة الرجوع (return). مثال ذلك:

def pow(x, y):
    return x ** y
y = pow(2, 3)

والأخرى: التغيير في مُعطىً قابل للتغيير (كالقائمة أو الملف). مثال ذلك:

def print_decorated(message: str, n: int):
    print("=" * n)
    print(message)
    print("=" * n)
print_decorated("Salam alykom", 15)

والكائنات قد يحصل فيها إحدى الأمرين لغرض ما.

فالقائمة (list) هي مظنَّة التغيير.

ففي نحو: sorted(xs) فإن الإجراء يُنتِجُ نُسخةً معدَّلة، ولا يغير القائمة الأصلية؛ وذلك يتطلَّبُ مساحة إضافية في الذاكرة أثناء العمليَّة. وقد يكون هذا مرغوبًا في البرامج التي تحتاج لمتابعة التغييرات الحاصلة، حيث يتم الاحتفاظ بالنُّسَخ البينية.

xs = [40, 20, 10, 30]
ys = sorted(xs)
print(xs, "لم يعمل الإجراء في القائمة نفسها")
print(ys, "هي قائمة جديدة")

وأما في نحو: xs.sort() فإن الطريقة (.sort()) تغيِّرُ القائمة المُسندَة؛ فلا تحتاجُ لنسخ القائمة في الذاكرة للتعديل عليها.

xs = [20, 10, 30, 40]
xs.sort()
print(xs)

تمرير المعطيات بالاسم

وقد تُعَيَّنُ المعطيات بأحد طريقتين:

  1. تعيين بالموضع: نحو: round(3.14159, 2)
  2. تعيين بالاسم: نحو: round(number=3.14159, ndigits=2) فلا يشترط فيه ترتيب المعطيات.

ويجوز استعمال الطريقتين معًا في نحو: list.sort(numbers, reverse=True) ويشترط فيه تقدم التعيين بالموضع ليكون في مكانه، ثم يتبعه التعيين بالاسم حيث لا يشترط الترتيب فيه.

وفي التعريف تكون المعطيات كثيرة في الإجراء على النحو التالي:

def weather_condition(temperature, humidity, wind_speed):
    if temperature >= 30 and humidity >= 60 and wind_speed >= 10:
        return "Rainy"
    elif temperature >= 20 and humidity >= 50 and wind_speed >= 5:
        return "Cloudy"
    elif temperature >= 10 and humidity >= 30 and wind_speed >= 0:
        return "Sunny"
    return "Normal"

ويكون طلبها بالطريقتين كما تقدَّم، بالموضع أو بالاسم. ولاحظ أن التمرير بالاسم يجوز فيه تبديل الترتيب، وأما القيمة التي تمرر بالموضع فلا بد أن تكون في الموضع.

cond = weather_condition(30, wind_speed=10, humidity=60)

if cond == "Rainy":
    print("Don't forget your umbrella!")

نطاق التسمية

ومن خصائصها أن المتغيرات في الداخل لا تظهر للخارج.

def calculate_bmi(weight, height):
    bmi = weight / (height ** 2)
    return round(bmi, 2)

فنتوقع وقوع خطأ هنا لأن bmi غير معرفة إلا في نطاق الإجراء:

print(bmi)

تقول رسالة الخطأ (السطر الأخير) أن المتغير bmi غير معرَّف. وهذا منطقي لأن النطاق الخارجي لا يعلم ما تكنه النطاقات الداخلية الخاصة بالإجراءات. وهو أمر مطلوب جدًّا ومرغوب في البرمجة. وذلك يعني أننا لن نتعب كثيرًا في اختيار الأسماء داخل كل إجراء، مخافة التعارض.