Skip to content

6. الوظائف

Image

6.1. البرنامج النصي [fonc_01]: نطاق المتغيرات

يُظهر البرنامج النصي [fonc_01] أمثلة على نطاق المتغيرات بين الدوال:

#  variable scope
def f1():
    #  avoid using global variables
    #  global variable i
    global i
    i += 1
    #  local variable j
    j = 10
    print(f"f1[i,j]=[{i},{j}]")


def f2():
    #  avoid using global variables
    #  global variable i
    global i
    i += 1
    #  local variable j
    j = 20
    print(f"f2[i,j]=[{i},{j}]")


def f3():
    #  local variable i
    i = 1
    #  local variable j
    j = 30
    print(f"f3[i,j]=[{i},{j}]")


#  main program
i = 0
j = 0
#  these two variables will only be known by a function f
#  only if it explicitly declares in the global instruction that it wants to use them
#  or that the function uses the global variable for reading only
f1()
f2()
f3()
#  j hasn't changed but i has
print(f"[i,j]=[{i},{j}]")

النتائج


C:\Data\st-2020\dev\python\cours-2020\python3-flask-2020\venv\Scripts\python.exe C:/Data/st-2020/dev/python/cours-2020/python3-flask-2020/fonctions/fonc_01.py
f1[i,j]=[1,10]
f2[i,j]=[2,20]
f3[i,j]=[1,30]
[i,j]=[2,0]
 
Process finished with exit code 0

ملاحظات:

  • يوضح البرنامج النصي استخدام المتغير i، الذي تم تعريفه كمتغير عام في الدالتين f1 و f2. في هذه الحالة، يتشارك البرنامج الرئيسي والدالتين f1 و f2 في استخدام المتغير i نفسه.

6.2. النص البرمجي [fonc_02]: نطاق المتغيرات

يعتمد البرنامج النصي [fonc_03] على البرنامج النصي [fonc_02] ويوضح كيفية تجنب استخدام المتغيرات العالمية:

#  variable scope
def f1(i):
    #  local variable i
    i += 1
    #  local variable j
    j = 10
    print(f"f1[i,j]=[{i},{j}]")
    #  return the modified value
    return i


def f2(i):
    #  local variable i
    i += 1
    #  local variable j
    j = 20
    print(f"f2[i,j]=[{i},{j}]")
    #  return the modified value
    return i


def f3():
    #  local variable i
    i = 1
    #  local variable j
    j = 30
    print(f"f3[i,j]=[{i},{j}]")


#  main program
i = 0
j = 0
#  these two variables will only be known by a function f
#  only if it explicitly declares in the global instruction that it wants to use them
#  or if the function uses the global variable for reading only
i = f1(i)
i = f2(i)
f3()
#  j hasn't changed but i has
print(f"[i,j]=[{i},{j}]")

تعليقات:

  • السطران 2 و 12: بدلاً من إعلان المتغير [i] كمتغير عام، يتم تمريره كمعلمة إلى الدالتين f1 و f2؛
  • السطران 9 و19: تُرجع الدالتان f1 وf2 المتغير [i] المعدل إلى البرنامج الرئيسي. ويسترده البرنامج الرئيسي في السطرين 36 و37؛

النتائج


C:\Data\st-2020\dev\python\cours-2020\python3-flask-2020\venv\Scripts\python.exe C:/Data/st-2020/dev/python/cours-2020/python3-flask-2020/fonctions/fonc_02.py
f1[i,j]=[1,10]
f2[i,j]=[2,20]
f3[i,j]=[1,30]
[i,j]=[2,0]
 
Process finished with exit code 0

6.3. البرنامج النصي [fonc_03]: نطاق المتغيرات

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

def f1():
    #  here the global variable i is known
    print(f"[f1] i={i}")
    #  here the global variable j is known
    print(f"[f1] j={j}")


def f2():
    #  here the global variable i is not known
    #  because the f2 function defines a local variable with the same name
    #  it then has priority
    try:
        #  try displaying the local variable i defined below
        print(f"[f2] i={i}")
        #  the following instruction makes i a local variable of function f2
        i = 7
    except BaseException as erreur:
        print(f"[f2] erreur={erreur}")


def f3():
    #  here the global variable i is not known
    #  because the f3 function defines a local variable with the same name
    #  it then has priority

    #  the following instruction makes i a local variable
    i = 7
    #  display - here i is known
    print(f"[f3] i={i}")


#  hand -----------
#  global variables to functions
i = 10
j = 20
#  call from f1
f1()
print(f"[main] i={i}, j={j}")
#  call from f2
f2()
print(f"[main] i={i}")
#  call from f3
f3()
print(f"[main] i={i}")

ملاحظات

  • السطر 34: يحدد الكود الرئيسي متغيرًا [i]؛
  • الأسطر 1–5: تستخدم الدالة f1 أيضًا المتغير [i] دون تعيين قيمة له. وهذا يمثل قراءة للمتغير [i]. في هذه الحالة، المتغير [i] المستخدم هو المتغير الموجود في كود الاستدعاء، السطر 34؛
  • الأسطر 8-18: تستخدم الدالة f2 أيضًا متغير [i] ولكنها تعين له قيمة في السطر 16. إن تعيين قيمة للمتغير [i] في f2 يجعل [i] تلقائيًا متغيرًا محليًا للدالة [f2]. وبالتالي، فإن هذه الدالة "تخفي" المتغير [i] عن كود الاستدعاء؛
  • السطر 14: ستفشل عملية الكتابة على المتغير المحلي [i] لأنه لا يحتوي على قيمة عند الوصول إلى السطر 14. يحصل على قيمته في السطر 16. سيحدث استثناء. لهذا السبب، تم وضع السطر 14 داخل كتلة try/catch؛
  • الأسطر 21–29: تقوم الدالة f3 بنفس ما تقوم به الدالة f2 ولكنها تُعرّف متغيرها المحلي [i] في وقت أبكر؛

النتائج


C:\Data\st-2020\dev\python\cours-2020\python3-flask-2020\venv\Scripts\python.exe C:/Data/st-2020/dev/python/cours-2020/python3-flask-2020/fonctions/fonc_03.py
[f1] i=10
[f1] j=20
[main] i=10, j=20
[f2] erreur=local variable 'i' referenced before assignment
[main] i=10
[f3] i=7
[main] i=10
 
Process finished with exit code 0

6.4. البرنامج النصي [fonc_04]: وضع تمرير المعلمات

النص البرمجي كما يلي:

#  function f1
def f1(a):
    a = 2


#  function f2
def f2(a, b):
    a = 2
    b = 3
    return a, b


#  ------------------------ hand
x = 1
f1(x)
print(f"x={x}")
(x, y) = (-1, -1)
(x, y) = f2(x, y)
print(f"x={x}, y={y}")

النتائج

1
2
3
4
5
C:\Data\st-2020\dev\python\cours-2020\python3-flask-2020\venv\Scripts\python.exe C:/Data/st-2020/dev/python/cours-2020/python3-flask-2020/fonctions/fonc_04.py
x=1
x=2, y=3

Process finished with exit code 0

ملاحظات:

  • كل شيء في Python هو كائن. بعض الكائنات تسمى "ثابتة": لا يمكن تعديلها. هذا هو الحال بالنسبة للأرقام والسلاسل والمجموعات. عندما يتم تمرير كائنات Python كحجج إلى الدوال، يتم تمرير مراجعها، ما لم تكن هذه الكائنات "ثابتة"، وفي هذه الحالة يتم تمرير قيمة الكائن؛
  • تهدف الدالتان f1 (السطر 2) و f2 (السطر 7) إلى توضيح تمرير معلمة الإخراج. نريد أن يتم تعديل المعلمة الفعلية للدالة بواسطة الدالة؛
  • السطران 2–3: تقوم الدالة f1 بتعديل معلمتها الشكلية a. نريد معرفة ما إذا كان المعلم الفعلي سيتم تعديله أيضًا؛
  • السطران 14–15: المعلمة الفعلية هي x = 1. يوضح السطر 2 من النتائج أن المعلمة الفعلية لم يتم تعديلها. وبالتالي، فإن المعلمة الفعلية x والمعلمة الشكلية a هما كائنان مختلفان؛
  • الأسطر 8–10: تقوم الدالة f2 بتعديل معلمتيها الشكلية a و b، وتُرجعهما كنتائج؛
  • السطور 17–18: يتم تمرير المعلمات الفعلية (x, y) إلى f2، ويتم تعيين نتيجة f2 إلى (x, y). يوضح السطر 3 من النتائج أن المعلمات الفعلية (x, y) قد تم تعديلها.

نستنتج أنه عندما تكون الكائنات "غير القابلة للتغيير" معلمات إخراج، يجب أن تكون جزءًا من النتائج التي تعيدها الدالة.

6.5. النص البرمجي [fonc_05]: ترتيب الدوال في النص البرمجي

يُظهر البرنامج النصي [fonc_05] أنه لا يمكن استدعاء دالة ما لم تكن قد وردت سابقًا في الكود:

#  ------------------------ hand
print(f2(100, 200))

#  function f1
def f1(a):
    return a + 10


#  function f2
def f2(a, b):
    return f1(a + b)

ملاحظات

  • السطر 2 سيتسبب في حدوث خطأ لأنه يستخدم الدالة f2، التي لم يتم تعريفها بعد في البرنامج النصي؛

النتائج

1
2
3
4
5
6
7
C:\Data\st-2020\dev\python\cours-2020\python3-flask-2020\venv\Scripts\python.exe C:/Data/st-2020/dev/python/cours-2020/python3-flask-2020/fonctions/fonc_05.py
Traceback (most recent call last):
  File "C:/Data/st-2020/dev/python/cours-2020/python3-flask-2020/fonctions/fonc_05.py", line 2, in <module>
    print(f2(100, 200))
NameError: name 'f2' is not defined

Process finished with exit code 1

6.6. البرنامج النصي [fonc_06]: ترتيب الدوال في البرنامج النصي

يوضح البرنامج النصي [fonc_06] أن ما ينطبق على كود الاستدعاء لا ينطبق على الدوال:

#  function f2
def f2(a, b):
    return f1(a + b)


#  function f1
def f1(a):
    return a + 10


#  ------------------------ hand
print(f2(100, 200))

ملاحظات

  • السطر 3: تستخدم الدالة [f2] الدالة [f1] المُعرَّفة لاحقًا في البرنامج النصي. ومع ذلك، لا يتسبب هذا في حدوث خطأ. وبالتالي، يمكننا استنتاج أن ترتيب تعريف الدوال في برنامج نصي بلغة Python لا يهم؛

النتائج

1
2
3
4
C:\Data\st-2020\dev\python\cours-2020\python3-flask-2020\venv\Scripts\python.exe C:/Data/st-2020/dev/python/cours-2020/python3-flask-2020/fonctions/fonc_06.py
310

Process finished with exit code 0

6.7. البرنامج النصي [fonc_07]: استخدام الوحدات النمطية

يوضح البرنامج النصي [fonc_07] كيفية عزل الوظائف في وحدة نمطية.

Image

نقوم بعزل الدوال القابلة لإعادة الاستخدام في وحدة نمطية. بدلاً من نقلها من نص برمجي إلى آخر:

  • نضعها في ملف منفصل نعلنه بطريقة محددة؛
  • تقوم البرامج النصية التي تحتاج إلى هذه الوظائف بـ"استيراد" الوحدة النمطية التي تحتوي عليها؛

النص البرمجي [fonctions_module_01] هو كما يلي:

1
2
3
4
5
6
7
#  function f2
def f2(a, b):
    return f1(a + b)

#  function f1
def f1(a):
    return a + 10

هناك عدة طرق لضمان إمكانية الرجوع إلى الدوال الموجودة في البرنامج النصي [fonctions_module_01] من قبل برامج نصية أخرى. تختلف هذه الطرق اعتمادًا على ما إذا كان البرنامج النصي يُشغَّل داخل [PyCharm] أم لا.

في [PyCharm يتم البحث عن الوحدات المستوردة في مجلدات محددة تسمى [Root Sources]. هناك طريقتان لجعل مجلد ما [Root Source]:

Image

  • في [4]، تغير لون المجلد؛

بعد هذه العملية، يتم التعرف على مجلد [functions/modules] كمجلد مصدر. يمكنك بعد ذلك الكتابة في البرنامج النصي:

from fonctions_module_01 import f2

لاستيراد/استخدام الدالة f2 المحددة في الوحدة النمطية [functions_module_01.py].

طريقة أخرى هي استخدام خصائص المشروع:

  • فيما سبق، يسمح التسلسل [1-6] باستخدام المجلد [shared] كمجلد لتخزين الوحدات النمطية المراد استيرادها؛

في الوقت الحالي، لن نعلن أي مجلد على أنه [جذر المصادر] بخلاف جذر المشروع:

Image

بمجرد الانتهاء من ذلك، يمكننا كتابة البرنامج النصي [fonc-07] التالي:

1
2
3
4
5
6
7
8
#  using modules
import sys

#  ------------------------ hand
print(f"Python path={sys.path}")
from fonctions.shared.fonctions_module_01 import f2

print(f2(100, 200))
  • السطر 2: نقوم باستيراد الكائن [sys] حتى نتمكن من استخدام سمة [path] الخاصة به في السطر 5، والتي توفر ما يُعرف باسم [مسار Python]: قائمة بالدلائل التي سيتم البحث فيها عن الوحدات النمطية المستوردة؛
  • السطر 6: نستورد الدالة f2 من الوحدة النمطية [fonctions_module_01]. للإشارة إلى هذه الوحدة النمطية، نستخدم المسار المؤدي من جذر المشروع إلى الوحدة النمطية. مع PyCharm، يتم تضمين جذر المشروع دائمًا في المجلدات التي يتم البحث فيها عند البحث عن وحدة نمطية مستوردة في نص برمجي. وبالتالي، فإن هذا المجلد جزء من [مسار Python] للمشروع. وهذا ما سيسمح لنا السطر 5 بالتحقق منه؛
  • السطر 6: إذا أردنا وصف المسار من جذر المشروع إلى مجلد [fonctions_module_01]، فسنكتب [fonctions/shared/fonctions_module_01]. في مسار الوحدة النمطية، يتم استبدال / بنقطة. لذلك نكتب [fonctions.modules.fonctions_module_01]؛
  • بعد السطر 6، يتم تعريف الدالة f2. نستخدمها في السطر 8؛

النتائج


C:\Data\st-2020\dev\python\cours-2020\python3-flask-2020\venv\Scripts\python.exe C:/Data/st-2020/dev/python/cours-2020/python3-flask-2020/fonctions/fonc_07.py
Python path=['C:\\Data\\st-2020\\dev\\python\\cours-2020\\python3-flask-2020\\fonctions', 'C:\\Data\\st-2020\\dev\\python\\cours-2020\\python3-flask-2020', 'C:\\Data\\st-2020\\dev\\python\\cours-2020\\python3-flask-2020\\fonctions\\shared', 'C:\\myprograms\\Python38\\python38.zip', 'C:\\myprograms\\Python38\\DLLs', 'C:\\myprograms\\Python38\\lib', 'C:\\myprograms\\Python38', 'C:\\Data\\st-2020\\dev\\python\\cours-2020\\python3-flask-2020\\venv', 'C:\\Data\\st-2020\\dev\\python\\cours-2020\\python3-flask-2020\\venv\\lib\\site-packages']
310
 
Process finished with exit code 0

أعلاه:

  • المظلل باللون الأخضر، يمكننا أن نرى أن جذر المشروع هو جزء من [مسار Python]؛
  • المظلل باللون الأصفر، يمكننا أن نرى أن المجلد الذي يحتوي على البرنامج النصي الذي تم تنفيذه هو أيضًا جزء من [مسار Python]؛
  • العناصر الأخرى في [مسار Python] تأتي مباشرة من مجلد تثبيت Python؛

ماذا يحدث عندما لا نستخدم PyCharm لتشغيل [fonc-07]؟

Image

Image

  • في [1]، نقوم بتشغيل البرنامج النصي [fonc-07]. نحن موجودون في مجلد [functions]؛
  • في [2]، نرى أن دليل التنفيذ جزء من [مسار Python]. وهذا هو الحال دائمًا. يمكننا أيضًا أن نرى أن الدليل الجذر [C:\\Data\\st-2020\\dev\\python\\cours-2020\\python3-flask-2020] ليس جزءًا من [مسار Python]؛
  • في [3]، يُبلغ مترجم Python أنه لا يمكنه العثور على الوحدة النمطية [fonctions]؛

للعثور على الوحدة المستوردة [fonctions.shared.fonctions_module_01]، يبحث مترجم Python في المجلدات الموجودة في [مسار Python] عن مجلد فرعي باسم [fonctions]. ولا يمكنه العثور عليه في أي مكان. وذلك لأن المجلد الفرعي [functions] موجود ضمن المجلد [C:\Data\st-2020\dev\python\cours-2020\python3-flask-2020 الذي لا يشكل جزءًا من [مسار Python].

يقدم البرنامج النصي [fonc-08] حلاً محتملاً لهذه المشكلة.

6.8. البرنامج النصي [fonc_08]: إضافة مجلدات إلى [مسار Python]

من الممكن تعديل [مسار Python] برمجياً، كما هو موضح في البرنامج النصي [fonc-08]:

#  using modules
import os
import sys

#  script folder
script_dir = os.path.dirname(os.path.abspath(__file__))
#  Python Path before modification
print(f"Python path avant={sys.path}")
#  add the [shared] folder to the Python Path
sys.path.append(f"{script_dir}/shared")
#  Python Path after modification
print(f"Python path après={sys.path}")

#  import f2
from fonctions_module_01 import f2

#  ------------------------ hand
print(f2(100, 200))

ملاحظات

  • السطر 4: المتغير الخاص [__file__] هو اسم البرنامج النصي الذي يتم تنفيذه. واعتمادًا على سياق التنفيذ، يمكن أن يكون هذا الاسم مطلقًا (في PyCharm) أو نسبيًا (في وحدة التحكم). تُرجع الدالة [os.path.abspath] المسار المطلق للملف الذي يتم تمرير اسمه إليها. وتُرجع الدالة [os.path.dirname] المسار المطلق للدليل الذي يحتوي على الملف الذي يتم تمرير اسمه إليها؛
  • السطر 10: [sys.path] هي قائمة تحتوي على أسماء الدلائل التي يتم البحث فيها عند البحث عن وحدة نمطية. نضيف جذر المشروع المحدد في السطر 4 إلى هذه القائمة؛
  • نعرض [مسار Python] قبل (السطر 8) وبعد (السطر 12) التعديل؛
  • السطر 15: نستورد الوحدة النمطية [fonctions_module_01]، التي تحتوي على الدالة f2؛

يؤدي التنفيذ في PyCharm إلى النتائج التالية:


C:\Data\st-2020\dev\python\cours-2020\python3-flask-2020\venv\Scripts\python.exe C:/Data/st-2020/dev/python/cours-2020/python3-flask-2020/fonctions/fonc_08.py
Python path avant=['C:\\Data\\st-2020\\dev\\python\\cours-2020\\python3-flask-2020\\fonctions', 'C:\\Data\\st-2020\\dev\\python\\cours-2020\\python3-flask-2020', 'C:\\Data\\st-2020\\dev\\python\\cours-2020\\python3-flask-2020\\fonctions\\shared', 'C:\\myprograms\\Python38\\python38.zip', 'C:\\myprograms\\Python38\\DLLs', 'C:\\myprograms\\Python38\\lib', 'C:\\myprograms\\Python38', 'C:\\Data\\st-2020\\dev\\python\\cours-2020\\python3-flask-2020\\venv', 'C:\\Data\\st-2020\\dev\\python\\cours-2020\\python3-flask-2020\\venv\\lib\\site-packages']
Python path après=['C:\\Data\\st-2020\\dev\\python\\cours-2020\\python3-flask-2020\\fonctions', 'C:\\Data\\st-2020\\dev\\python\\cours-2020\\python3-flask-2020', 'C:\\Data\\st-2020\\dev\\python\\cours-2020\\python3-flask-2020\\fonctions\\shared', 'C:\\myprograms\\Python38\\python38.zip', 'C:\\myprograms\\Python38\\DLLs', 'C:\\myprograms\\Python38\\lib', 'C:\\myprograms\\Python38', 'C:\\Data\\st-2020\\dev\\python\\cours-2020\\python3-flask-2020\\venv', 'C:\\Data\\st-2020\\dev\\python\\cours-2020\\python3-flask-2020\\venv\\lib\\site-packages', 'C:\\Data\\st-2020\\dev\\python\\cours-2020\\python3-flask-2020\\fonctions/shared']
310
 
Process finished with exit code 0
  • السطر 3: نرى أن المجلد [shared] يظهر مرتين في [Python Path]. يمكننا تجنب ذلك، لكنه لا يسبب أي مشاكل هنا؛
  • السطر 4: تم تنفيذ الدالة f2 بنجاح؛

الآن دعونا نشغل [fonc-08] في محطة طرفية:


(venv) C:\Data\st-2020\dev\python\cours-2020\python3-flask-2020\fonctions>python fonc_08.py
Python path avant=['C:\\Data\\st-2020\\dev\\python\\cours-2020\\python3-flask-2020\\fonctions', 'C:\\myprograms\\Python38\\python38.zip', 'C:\\myprograms\\Python38\\DLLs', 'C:\\myprograms\\Python38\\lib', 'C:\\myprograms\\Python38', 'C:\\Data\\st-2020\\dev\\python\\cours-2020\\python3-flask-2020\\venv', 'C:\\Data\\st-2020\\dev\\python\\cours-2020\\python3-flask-2020\\venv\\lib\\site-packages']
Python path après=['C:\\Data\\st-2020\\dev\\python\\cours-2020\\python3-flask-2020\\fonctions', 'C:\\myprograms\\Python38\\python38.zip', 'C:\\myprograms\\Python38\\DLLs', 'C:\\myprograms\\Python38\\lib', 'C:\\myprograms\\Python38', 'C:\\Data\\st-2020\\dev\\python\\cours-2020\\python3-flask-2020\\venv', 'C:\\Data\\st-2020\\dev\\python\\cours-2020\\python3-flask-2020\\venv\\lib\\site-packages', 'C:\\Data\\st-2020\\dev\\python\\cours-2020\\python3-flask-2020\\fonctions/shared']
310
  • السطر 2: كما في السابق، المجلد [shared] غير موجود في [Python Path]؛
  • السطر 3: الآن هو موجود؛
  • السطر 4: تم العثور على الدالة f2؛

6.9. النص البرمجي [fonc_09]: إعلان أنواع المعلمات

يُظهر البرنامج النصي [fonc_09] أنه يمكنك تعريف نوع معلمات الدالة وكذلك نوع النتيجة. ومع ذلك، فإن هذا التعريف مفيد فقط لتوثيق الدالة. لا يتحقق مترجم Python مما إذا كانت معلمات الدالة الفعلية من النوع المتوقع أم لا. ومع ذلك، يقوم PyCharm بتمييز حالات عدم اتساق الأنواع بين المعلمات الفعلية والشكلية. وهذا السبب وحده يجعل تعريفات الأنواع أمرًا لا غنى عنه.

النص البرمجي كما يلي:

#  a function with parameter type indication
#  this is for documentation purposes only, as the python interpreter ignores it


def show(param: int) -> int:
    print(f"param={param}, type(param)={type(param)}")
    return param + 1


#  hand -------------------------
print(show(4))
show("xyz")

ملاحظات:

  • السطر 5: نعلن أن المعلمة الشكلية [param] من النوع [int] وأن نوع قيمة الإرجاع للدالة هو أيضًا [int]؛
  • السطر 11: المعلمة الفعلية للدالة [show] من النوع الصحيح؛
  • السطر 12: المعلمة الفعلية للدالة [show] ليست من النوع الصحيح؛

النتائج

C:\Data\st-2020\dev\python\cours-2020\python3-flask-2020\venv\Scripts\python.exe C:/Data/st-2020/dev/python/cours-2020/python3-flask-2020/fonctions/fonc_09.py
param=4, type(param)=<class 'int'>
5
param=xyz, type(param)=<class 'str'>
Traceback (most recent call last):
  File "C:/Data/st-2020/dev/python/cours-2020/python3-flask-2020/fonctions/fonc_09.py", line 11, in <module>
    show("xyz")
  File "C:/Data/st-2020/dev/python/cours-2020/python3-flask-2020/fonctions/fonc_09.py", line 6, in show
    return param + 1
TypeError: can only concatenate str (not "int") to str

Process finished with exit code 1
  • السطر 10: نوع المعلمة [param] هو [str]. عندما تظهر هذه الرسالة، نكون قد أدخلنا بالفعل كود الدالة [show]. وبالتالي، فقد قبل مترجم Python أن المعلمة الفعلية للدالة [show] هي من النوع [str]؛
  • السطر 7 من الكود يطلق الاستثناء الموضح في الأسطر 4–10 من النتائج؛

ومع ذلك، يشير PyCharm إلى وجود مشكلة:

Image

في [1]، قام PyCharm بتمييز الاستدعاء غير الصحيح.

6.10. النص البرمجي [fonc_10]: المعلمات المسماة

لتمرير المعلمات إلى دالة، يمكنك استخدام أسماء معلماتها الشكلية. في هذه الحالة، لست ملزمًا باتباع ترتيب المعلمات الشكلية:

1
2
3
4
5
6
7
#  we can refer to the actual parameters by their formal names
def f(x, y):
    return x + y


#  hand
print(f(y=10, x=3))

ملاحظات

  • السطر 2: الدالة f لها معلمتان رسميتان، x و y؛
  • السطر 7: عند استدعاء الدالة f، يمكنك استخدام أسماء المعلمات الشكلية. قد تكون هذه الممارسة مفيدة في حالتين على الأقل:
    • تحتوي الدالة على العديد من المعلمات، ومعظمها له قيم افتراضية. عند استدعاء الدالة، تسمح لك التقنية الموضحة أعلاه بتهيئة المعلمات التي لا تريد استخدام القيمة الافتراضية لها فقط؛
    • إذا كانت المتغيرات الشكلية تحمل أسماء ذات معنى، فإن استخدام المتغيرات المسماة في استدعاء الدالة يحسن قابلية قراءة الكود؛

النتائج

1
2
3
4
C:\Data\st-2020\dev\python\cours-2020\python3-flask-2020\venv\Scripts\python.exe C:/Data/st-2020/dev/python/cours-2020/python3-flask-2020/fonctions/fonc_10.py
13

Process finished with exit code 0

6.11. البرنامج النصي [fonc_11]: دالة متكررة

البرنامج النصي [fonc_11] هو مثال على دالة متكررة (تستدعي نفسها):

#  recursive function
def fact(i: int) -> int:
    #  factorial(1) is 1
    #  a recursive function must terminate at a certain point
    if i == 1:
        return 1
    else:
        #  factorial(i)=i*factorial(i-1)
        return i * fact(i - 1)


#  ---------- hand
print(f"fact(8)={fact(8)}")

تعليقات

  • الأسطر 1-9: دالة المضاعف؛
  • السطر 9: الدالة [المضروب] تستدعي نفسها؛
  • السطران 5-6: يجب أن تتوقف الدالة التكرارية دائمًا عند استيفاء شرط ما؛ وإلا، فسيكون لدينا تكرار لانهائي؛

النتائج

1
2
3
4
C:\Data\st-2020\dev\python\cours-2020\python3-flask-2020\venv\Scripts\python.exe C:/Data/st-2020/dev/python/cours-2020/python3-flask-2020/fonctions/fonc_11.py
fact(8)=40320

Process finished with exit code 0

6.12. البرنامج النصي [fonc_12]: دالة تكرارية

توفر الدالة [fonc_12] مزيدًا من التفاصيل حول كيفية عمل التكرار:

#  recursive function
#  behavior of parameter j


def fact(i: int, j: int) -> int:
    #  stop recursive function
    if i == 1:
        print(f"j={j}")
        return 1
    else:
        #  we manipulate j
        j += 1
        print(f"avant fact j={j}")
        #  recursivity
        f = fact(i - 1, j)
        print(f"après fact j={j}")
        #  result
        return i * f


#  ---------- hand
print(f"fact(8)={fact(8, 0)}")

تعليقات

  • السطر 5: ما زلنا نركز على دالة المضاعفات. نضيف المعلمة [j] إليها؛
  • السطر 12: يتم زيادة المتغير j بانتظام مع كل عملية حسابية للمضروب. نعرض قيمته قبل (السطر 12) وبعد (السطر 16) التكرار (السطر 15)؛

النتائج

C:\Data\st-2020\dev\python\cours-2020\python3-flask-2020\venv\Scripts\python.exe C:/Data/st-2020/dev/python/cours-2020/python3-flask-2020/fonctions/fonc_12.py
avant fact j=1
avant fact j=2
avant fact j=3
avant fact j=4
avant fact j=5
avant fact j=6
avant fact j=7
j=7
après fact j=7
après fact j=6
après fact j=5
après fact j=4
après fact j=3
après fact j=2
après fact j=1
fact(8)=40320

Process finished with exit code 0
  • الأسطر 2–8: نرى أن قيمة [j] تزداد طالما استمرت التكرار حتى تفي بالشرط الذي يتوقف عنده التكرار. ومن تلك النقطة فصاعدًا، يحدث العودة من استدعاءات الدالة [fact] بترتيب عكسي للاستدعاءات؛
  • الأسطر 10–16: تعكس هذه العروض العوائد المتتالية من استدعاء factorial. تعود المتغير [j] إلى قيمتها الأولية 1؛