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

الكائنات والتابعات

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

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

  • ستعرف ما هو الكائن في البرمجة
  • ستفهم المقصود باستقلالية الكائنات المنفردة
  • ستكون قادرًا على إنشاء الكائنات والوصول إليها

هذا هو الجزء الأول من دورة البرمجة المتقدمة. وقد صُمِّم هذا المحتوى لاستخدامه مع محرّر Visual Studio Code، تمامًا كما كان الحال مع دورة مقدمة إلى البرمجة السابقة. إن لم تستخدم Visual Studio Code من قبل، فستجد تعليمات التثبيت هنا، ومقدمة عن بيئة البرمجة من الدورة السابقة هنا.

في دورة مقدمة إلى البرمجة لاحظنا أنه من الفائدة كثيرًا تجميع البيانات المترابطة معًا في برامجنا. فمثلًا، إذا كنا نحاول تخزين معلومات عن كتاب، فقد يكون من المناسب استخدام صف (tuple) أو قاموس (dictionary) لتنظيم البيانات في هيكل بيانات واحد.

قد يبدو الحل على النحو التالي عند استخدام صف:

name = "In Search of Lost Typing"
author = "Marcel Pythons"
year = 1992

# Combine these in a tuple
book = (name, author, year)

# Print the name of the book
print(book[0])

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

name = "In Search of Lost Typing"
author = "Marcel Pythons"
year = 1992

# Combine these in a dictionary
book = {"name": name, "author": author, "year": year}

# Print the name of the book
print(book["name"])

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

ولو أنشأنا تمثيلين لهيكل مطابق لكتابين، باستخدام قواميس لها مفاتيح متطابقة، لما كان لأي تغييرات تُجرى في أحدهما أي تأثير على الآخر:

book1 = {"name": "The Old Man and the Pythons", "author": "Ernest Pythons", "year": 1952}
book2 = {"name": "Seven Pythons", "author": "Aleksis Python", "year": 1894}

print(book1["name"])
print(book2["name"])

book1["name"] = "A Farewell to ARM Processors"

print(book1["name"])
print(book2["name"])
The Old Man and the Pythons
Seven Pythons
A Farewell to ARM Processors
Seven Pythons

8_1_1.png

كائنات Python

قد تتذكّر من دورة مقدمة إلى البرمجة أن أي قيمة في Python تُعالَج داخليًّا بوصفها كائنًا. وهذا يعني أن القيمة المخزّنة في متغيّر هي مرجع إلى كائن. والبيانات بحد ذاتها مخزّنة داخل الكائن في ذاكرة الحاسوب. فإذا أسندت قيمة إلى متغيّر جديد بالأمر a = 3، فالقيمة المخزّنة في المتغيّر ليست 3، بل هي مرجع إلى كائن يحوي القيمة 3.

تضمّن معظم لغات البرمجة الأخرى (على الأقل تلك التي تدعم البرمجة الكائنية) بعض أنواع البيانات الأولية المعرَّفة خصيصًا. وتشمل هذه عادةً على الأقل الأعداد الصحيحة والأعداد العشرية وقيم الصدق المنطقية. وتُعالَج الأنواع الأولية معالجة مباشرة، أي أنها تُخزَّن مباشرة في المتغيّرات لا كمراجع. ولا تملك Python مثل هذه الأنواع الأولية، لكن التعامل مع أنواع البيانات الأساسية في Python مشابه عمليًّا جدًّا لذلك. وكائنات هذه الأنواع الأساسية (مثل الأعداد والقيم المنطقية والسلاسل النصية) غير قابلة للتغيير (immutable)، أي أنه لا يمكن تغييرها في الذاكرة. وإذا كان لا بدّ من تغيير القيمة المخزّنة في متغيّر من نوع بيانات أساسي، فُستبدل القيمة كلها بمرجع جديد، بينما يبقى الكائن نفسه سليمًا في الذاكرة.

الكائنات والتابعات

البيانات المخزّنة في كائن يمكن الوصول إليها عبر التابعات (methods). والتابع دالة تعمل على الكائن المحدَّد الذي ارتبطت به. وميّز التابعات عن الدوال الأخرى هو طريقة استدعائها: تكتب أولًا اسم الكائن المستهدف، يتبعه نقطة، ثم اسم التابع، مع الوسائط إن وُجدت. فمثلًا، يُرجع التابع values كل القيم المخزّنة في كائن من نوع القاموس، أو dict:

# this creates an object of type dictionary with the name book
book = {"name": "The Old Man and the Pythons", "author": "Ernest Pythons", "year": 1952}

# Print out all the values
# The method call values() is written after the name of the variable
# Remember the dot notation!
for value in book.values():
    print(value)
The Old Man and the Pythons
Ernest Pythons
1952

وبالمثل، تستهدف تابعات السلسلة النصية كائن السلسلة النصية التي تُستدعى عليها. ومن أمثلة تابعات السلسلة النصية count وfind:

name = "Imaginary Irene"

# Print out the number of times the letter I is found
print(name.count("I"))

# The number of letters I found in another string
print("Irreverent Irises in Islington".count("I"))

# The index of the substring Irene
print(name.find("Irene"))

# This string has no such substring
print("A completely different string".find("Irene"))
2
3
10
-1

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

my_list = [1,2,3]

# Add a couple of items
my_list.append(5)
my_list.append(1)

print(my_list)

# Remove the first item
my_list.pop(0)

print(my_list)
[1, 2, 3, 5, 1]
[2, 3, 5, 1]

تمرين برمجي: أصغر متوسط نتيجة

يُرجى كتابة دالة اسمها smallest_average(person1: dict, person2: dict, person3: dict)، تأخذ ثلاثة كائنات قاموس كوسيطات لها.

تحتوي كل كائن قاموس على قيم مسنودة إلى المفاتيح التالية:

  • "name": اسم المتسابق
  • "result1": النتيجة الأولى للمتسابق (عدد صحيح بين 1 و10)
  • "result2": النتيجة الثانية للمتسابق (كما سبق)
  • "result3": النتيجة الثالثة للمتسابق (كما سبق)

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

ويمكنك أن تفترض ألّا توجد تعادلات، أي أن متسابقًا واحدًا فقط سيملك متوسط النتيجة الأصغر.

ومثال على عمل الدالة:

person1 = {"name": "Mary", "result1": 2, "result2": 3, "result3": 3}
person2 = {"name": "Gary", "result1": 5, "result2": 1, "result3": 8}
person3 = {"name": "Larry", "result1": 3, "result2": 1, "result3": 1}

print(smallest_average(person1, person2, person3))
{'name': 'Larry', 'result1': 3, 'result2': 1, 'result3': 1}

تمرين برمجي: مجاميع الصفوف

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

يُرجى كتابة دالة اسمها row_sums(my_matrix: list)، تأخذ مصفوفة من الأعداد الصحيحة كوسيط لها.

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

ومثال على عمل الدالة:

my_matrix = [[1, 2], [3, 4]]
row_sums(my_matrix)
print(my_matrix)
[[1, 2, 3], [3, 4, 7]]