ملحق I — القاموس
وراجع خريطة المجموعات: شكل P.1
القاموس (dict
) جمع متغير مرتب من المفاتيح المرقَّمة الفريدة، تقابل كل منها قيمةً.
- متغير: يعني قبول الإضافة والحذف والتعديل
- مرتب: يعني أن لكل مفتاحٍ موضِعًا بالنسبة لبدايته.
- المفتاح والقيمة: هي عناصر المقابلة؛ حيث يدلّ المفتاح على القيمة.
- مرقَّمة: فيكون لكل مفتاح رقم هو ناتج عن عملية التجزئة (Hash) وهو الذي يدلّ على القيمة في واقع الأمر (وليس المفتاح ذاته).
- فريدة: يعني أن المفتاح لا يتكرر.
ينشأ القاموس بالإجراء المنشئ dict()
أو بالقوسين المتعرجين {}
وذلك على النحو التالي:
= {
d 'key1': 'value1',
'key2': 'value2',
}= dict(key1='value1', key2='value2')
d1 = dict([('key1', 'value1'), ('key2', 'value2')])
d2 assert d == d1 == d2
ولاحظ أن القاموس عبارة عن مجموعة اقترانات أو مقابلات:
- فيسمى المتغير
key1
المفتاح (ويشترط أن يكون قابلًا للتجزئة -hash
) - ويسمى ما يقترن به (مثل
value1
) بالقيمة
يستعمل القاموس في كثير من السياقات في البرمجة، وهو من أهم هياكل البيانات.
استعمالات القاموس
الكلمة ومعناها
القاموس بالمعنى الذي يشير إليه اللفظ. نفترض أن لدينا قاموسًا يحتوي على ترجمة بعض الكلمات من الإنجليزية إلى العربية:
= {
english_to_arabic 'apple': 'تفاحة',
'banana': 'موزة',
'orange': 'برتقالة',
}
ربط الأسماء بالأرقام
مثلاً: دليل أرقام الهواتف هو قاموس:
= {
name_to_phone 'Adam': '966xxxxxxxxx',
'Mohammed': '966xxxxxxxxx',
}
دليل أسماء النطاقات
وكذلك دليل أسماء النطاقات (DNS: Domain Name System) على شبكة الانرتنت هو قاموس:
= {
domain_to_ip 'google.com': '172.217.14.206',
'wikipedia.org': '103.86.96.10',
}
اختصار الروابط الطويلة
من استعمالات القاموس: اختصار الروابط الطويلة في روابط قصيرة.
= {
short_to_full 'google': 'https://www.google.com',
'python': 'https://www.python.org',
'wiki': 'https://www.wikipedia.org',
}
الكلمات المختصرة
أو الاختصارات إلى الكلمة التامة:
= {
abb_to_full 'ASAP': 'As Soon As Possible',
'BRB': 'Be Right Back',
'DIY': 'Do It Yourself',
'EDA': 'Exploratory Data Analysis',
'FYI': 'For Your Information',
'SAR': 'Saudi Riyal',
}
القاموس (dict
)
ومن حيث كون القاموس من نوع الجمع (Collection
)، فإنه يقبل الإجراءات ثلاثة:
- العضوية:
x not in d
- العد:
len(d)
- التكرار:
for x in d
ويقبل القاموس لكونه مقابلة (Mapping
) الإجراءات التالية:
- الإشارة مفتاح:
dict[key]
- الإشارة بمفتاح مع الرجوع بقيمة ابتدائية إن لم يُعثَر عليه:
dict.get(key[, default])
ولكونه مقابلة متغيرة (MutableMapping
)، فإنه يقبل الإجراءات التالية:
- التعديل بمفتاح:
dict[key] = value
- الحذف بمفتاح:
del dict[key]
- نزع بمفتاح وإرجاع القيمة:
x = dict.pop(key)
- التحديث:
dict.update(mapping)
راجع خريطة الجموع: شكل P.1.
وإليك جدول طرق القاموس:
الفعل | عمله |
---|---|
dict.clear() |
تزيل جميع العناصر من القاموس. |
dict.get(key[, default]) |
ترجع قيمة المفتاح key . إذا لم يكن المفتاح موجودًا، فإنها ترجع default (أو القيمة العدمية None إذا لم يتم توفير قيمة افتراضية default ). |
dict.items() |
ترجع عرضًا لعناصر القاموس (أزواج المفتاح والقيمة). |
dict.keys() |
ترجع عرضًا لمفاتيح القاموس. |
dict.values() |
ترجع عرضًا لقيم القاموس. |
dict.pop(key[, default]) |
تزيل المفتاح key وتعيد قيمته. إذا لم يكن المفتاح موجودًا، يتم إرجاع default إذا تم توفيره، وإلا يتم رفع خطأ KeyError . |
dict.popitem() |
تزيل وتعيد زوجًا عشوائيًا (مفتاح، قيمة) من القاموس. يتم ترتيب الأزواج بترتيب LIFO (الأخير يدخل أولاً) في الإصدارات قبل Python 3.7. |
dict.setdefault(key[, default]) |
إذا كان المفتاح key موجودًا في القاموس، فإنه يعيد قيمته. إذا لم يكن كذلك، فإنه يُدخل المفتاح مع القيمة default ويعيد default . |
dict.update([other]) |
تقوم بتحديث القاموس بالمفاتيح/القيم من other ، مع الكتابة فوق المفاتيح الموجودة. |
dict.fromkeys(iterable[, value]) |
ينشئ قاموسًا جديدًا بمفاتيح من iterable وقيم تم تعيينها على value (افتراضيًا None ). |
dict.copy() |
ترجع نسخة سطحية من القاموس. |
وهذه كذلك، كلها قابلة للتجزئة، ولا يشترط أن تكون متجانسة (من نفس النوع)، كما يلي:
= {
data # مقابلة نص بعدد
'key1': 100,
# مقابلة عدد بنص
20: 'value2',
# مقابلة نص بقائمة
'c': [10, 20, 30, True],
# مقابلة صف من أعداد بنص
1, 2): 'value3',
(
# مقابلة صف من نصوص بنص
'a', 'b', 'c'): 'value4',
(
}
assert len(data) == 5
del data['key1']
assert 'key1' not in data
ونحصل عليها بالإشارة بأحد المفاتيح:
print(data[20])
print(data['c'])
print(data[(1, 2)])
print(data[('a', 'b', 'c')])
value2
[10, 20, 30, True]
value3
value4
التضمين
وقد تكون البيانات متضمنة بعضها في بعض، كتفضيلات المستخدم (user
):
= {
user "name": "Adam",
"language": "Arabic",
"phone": "966xxxxxxxxx",
"last_updated": "2021-09-01",
"age": 25,
"notifications": {
"email": "monthly",
"sms": "weekly",
"push": "daily"
},"emails": ["example1@domain.com", "example2@domain.com"]
}
فالمفتاح (Key) عادةً ما يكون نصًّا كما ترى. وأما القيمة (Value) فقد تكون نصًّا أو عددًا أو قائمة أو حتى قاموسًا!
وللوصول إلى قيمة مضمَّنة، قد تكتب:
= user['notifications']
a print(a)
{'email': 'monthly', 'sms': 'weekly', 'push': 'daily'}
= a['sms']
b print(b)
weekly
وذلك أن نوع قيمة المتغير a
هو قاموس:
type(a)
dict
أو تأتي بها مرة واحدة:
= user['notifications']['sms']
c print(c)
weekly
وكذا الأمر في الوصول للقائمة المضمَّنة (emails
) كما يلي:
= user['emails']
e print(e)
['example1@domain.com', 'example2@domain.com']
ثم الوصول إلى عنصرٍ من هذه القائمة:
print(e[0])
example1@domain.com
وذلك أن نوع قيمة المتغير c
هو قائمة:
type(e)
list
أو الوصول إليها مرة واحدة:
= user['emails'][0]
f print(f)
example1@domain.com
ومن الأنماط المستعملة بكثرة: استعمال القواميس كعناصر لقائمة. ولذلك وجب علينا التدرب على قراءتها.
فمثلاً هذه قائمة يحتوي كل عنصرٍ منها على قاموس لبيانات مُرَشَّح للتوظيف، ونريد أن نستخلص خبراتهم المهنية منها:
= [
data
{'name': 'Ahmad Hamada',
'experiences': [
{'company': 'Geo Space',
'start': '2038-01-01',
'end': '2039-01-01',
'role': 'Junior Software Engineer',
},
{'company': 'Space Roots',
'start': '2039-01-01',
'end': '2041-01-01',
'role': 'Senior Software Engineer',
},
],
},
{'name': 'Belal Banana',
'experiences': [
{'company': 'Banana Tech',
'start': '2041-01-01',
'end': '2042-01-01',
'role': 'Smoothie Operator',
},
{'company': 'BugSquash Labs',
'start': '2042-02-01',
'end': '2043-08-01',
'role': 'Code Pest Control Specialist',
},
{'company': 'Caffeinated Circuits Inc.',
'start': '2043-09-01',
'end': '2045-05-01',
'role': 'Espresso-Driven Engineer',
}
]
}, ]
ولنفترض أننا نريد آخر وظيفة شغلها المرشح الثاني، فإننا نكتبها في بايثون بهذا الشكل:
1]['experiences'][-1]['role'] data[
'Espresso-Driven Engineer'
وبايثون تقيِّمها (أي: تحسبها أو تفسِّرها) من اليسار إلى اليمين، على النحو التالي:
من المتغير data
أريد العنصر الثاني، ومنه أريد مقابل المفتاح experiences
، ومنه أريد العنصر الأخير، ومنه أريد مقابل المفتاح role
.
وقد يكون فصلها أوضَح هكذا:
- من المتغير
data
(هو قائمة) - منه: العنصر الثاني (
1
) (هو قاموس) - منه: مقابل المفتاح
experiences
(هو قائمة) - منه: العنصر الأخير (هو قاموس)
- منه: مقابل المفتاح
role
(هو نص)
فإذا أردت أن تقرأها بالعكس من اليمين إلى اليسار، فتقول:
- مقابل المفتاح
role
- في العنصر الأخير من
- مقابل المفتاح
experiences
- في العنصر الثاني (
1
) من - المتغير
data
وتقول أيضًا: أريد وظيفةَ آخر خبرات الثاني من المرشحين.
قراءة صيَغ الوصول هي من مهارات المبرمج الذي يحتاجها كثيرًا.
الكر
ويحصل الكر بثلاثة طرق:
- كر المفاتيح:
for key in d.keys()
- كر القيم:
for value in d.values()
- كر العناصر:
for key, value in d.items()
(ينتج عنها أزواج (2-tuple
) من الفاتيح والقيم)
مثال:
= {
d 'A': 'Salam',
'B': 'Hello',
'C': 'Hi',
}for value in d.values():
print(value)
Salam
Hello
Hi
عكس القاموس
إذا أردت عكس القاموس بحيث يصير المفتاح مكان القيمة والقيمة مكان المفتاح، فبهذه الطريقة:
= {
d 'ASAP': 'As soon as possible',
'TBD': 'To be determined',
'IDK': 'I don\'t know',
}= dict()
inverse for k, v in d.items():
= k
inverse[v] inverse
{'As soon as possible': 'ASAP',
'To be determined': 'TBD',
"I don't know": 'IDK'}
أو بالجملة المختصرة:
= {v: k for k, v in d.items()}
inverse inverse
{'As soon as possible': 'ASAP',
'To be determined': 'TBD',
"I don't know": 'IDK'}
إنشاء قاموس من سلسلتين
ويتحصل القاموس من سلسلتين باستعمال الإجراء zip()
، كما يلي:
= ['Ahmad', 'Belal', 'Camal', 'Dawood']
students = [ 90, 80, 75, 85]
marks = dict(zip(students, marks))
data data
{'Ahmad': 90, 'Belal': 80, 'Camal': 75, 'Dawood': 85}