إنشاء وتحديث أزواج المفاتيح والقيم
سنتعلم الآن كيف نضيف أزواج مفتاح وقيمة جديدة إلى القاموس، مثلما نحتاج عند تسجيل ما يشتريه العميل.
قبل القواميس، لنراجع سريعًا طريقة إضافة عناصر إلى قائمة. شغّل البرنامج:
cart = []
cart.append('dog')
cart.append('box')
print(cart)
بسيط. ويمكننا أيضًا تغيير القيمة الموجودة عند فهرس معين واستبدالها بقيمة أخرى:
cart = ['dog', 'cat']
cart[1] = 'box'
print(cart)
ماذا لو حاولنا استخدام الإسناد بالفهرس لإنشاء عناصر القائمة من البداية؟ نعرف أننا نريد cart[0] مساوية لـ'dog' وcart[1] مساوية لـ'box'، فلنجرب أن نقول ذلك مباشرة:
cart = []
cart[0] = 'dog'
cart[1] = 'box'
print(cart)
هذا غير مسموح مع القوائم: الإسناد باستخدام الفهرس يعمل فقط مع فهرس صالح موجود بالفعل.
لكن القواميس مختلفة. جرّب:
quantities = {}
quantities['dog'] = 500
quantities['box'] = 2
print(quantities)
لاحظ أن {} تعني قاموسًا فارغًا، أي لا يحتوي على أي أزواج مفتاح وقيمة. وهي تشبه [] للقائمة الفارغة و"" للنص الفارغ.
عندما تسند قيمة إلى مفتاح غير موجود في قاموس، يُنشأ زوج المفتاح والقيمة الجديد.
هذا بالضبط ما نحتاجه. سواء أراد العميل 500 كلب أو خمسة ملايين، نستطيع وضع المعلومة مباشرة في قاموس الكميات.
اكتب دالة عامة اسمها buy_quantity(quantities, item, quantity) تضيف زوجًا جديدًا من المفتاح والقيمة إلى قاموس quantities:
def buy_quantity(quantities, item, quantity):
...
def test():
quantities = {}
buy_quantity(quantities, 'dog', 500)
check_result(quantities, {'dog': 500})
buy_quantity(quantities, 'box', 2)
check_result(quantities, {'dog': 500, 'box': 2})
test()
يجب أن تعدّل buy_quantity القاموس الذي استلمته مباشرة، ولا تحتاج إلى return أو print. يمكنك افتراض أن item غير موجود مسبقًا في quantities.
جسم الدالة يحتاج سطرًا واحدًا فقط. حوّل الفكرة المحددة quantities['dog'] = 500 إلى صيغة عامة تستخدم المتغيرين item وquantity من دون وضعهما بين علامات اقتباس.
جسم
buy_quantityيحتاج إلى سطر بسيط واحد فقط.يشبه بعض الأسطر في الخطوة السابقة، لكن استخدم متغيرات بدل القيم المكتوبة مباشرة.
انتبه لعلامات الاقتباس!
'dog'مثال لقيمة يمكن أن يأخذهاitem.ما مثال قيمة يمكن أن يأخذها
quantity؟بالنسبة إلى
'dog'كانت القيمة أعلاه500.أنت تكتب نسخة عامة من
quantities['dog'] = 500.اترك
quantitiesكما هي.واترك
[]و=أيضًا.تذكر أن
itemمتغير، بينما'item'قيمة نصية.استبدل
'dog'بـitem.استبدل
500بـquantity.لا تستخدم
'item'أو'quantity'؛ استخدم المتغيرينitemوquantityمباشرة.
أحسنت! جرّب الدالة الآن بصورة تفاعلية:
def buy_quantity(quantities, item, quantity):
quantities[item] = quantity
def test():
quantities = {}
for _ in range(3):
print('What would you like to buy?')
item = input()
print('How many?')
quantity = int(input())
buy_quantity(quantities, item, quantity)
print("OK, here's your cart so far:")
print(quantities)
test()
انتبه إلى الجزء int(input()): الدالة input() تعيد نصًا، بينما quantity يجب أن تكون عددًا صحيحًا. إذا أدخل المستخدم شيئًا ليس رقمًا فسيحدث خطأ، وهذا مقبول في هذه المرحلة.
شكرًا للتسوق معنا! لنحسب الآن المبلغ الذي أنفقته على كل نوع من المنتجات على حدة.
كتبنا سابقًا total_cost(quantities, prices) التي تعيد رقمًا واحدًا يمثل الإجمالي الكلي. الآن اكتب total_cost_per_item(quantities, prices) بحيث تعيد قاموسًا جديدًا فيه التكلفة الإجمالية لكل عنصر:
def total_cost_per_item(quantities, prices):
totals = {}
for item in quantities:
___ = quantities[item] * prices[item]
return totals
check_result(
total_cost_per_item({'apple': 2}, {'apple': 3, 'box': 5}),
{'apple': 6},
)
check_result(
total_cost_per_item({'dog': 500, 'box': 2}, {'dog': 100, 'box': 5}),
{'dog': 50000, 'box': 10},
)
املأ الجزء ___. في الاختبار الأول اشترى العميل تفاحتين وسعر الواحدة 3، لذلك يجب أن يحتوي القاموس الجديد على 'apple': 6. المفتاح هو item، والقيمة هي quantities[item] * prices[item]، والقاموس الذي نبنيه هو totals.
لا تحتاج إلا إلى ملء الجزء
___.ويمكنك، إن أردت، وضع اسم متغير هناك ثم إضافة سطر جديد تحته.
انظر إلى اختبارات
check_result. في المثال الأول الناتج المتوقع هو{'apple': 6}. لماذا؟لأن العميل اشترى تفاحتين، وسعر كل تفاحة 3، فالتكلفة الإجمالية
2 * 3 = 6.الجزء
'box': 5لا يدخل في الحساب لأن العميل لم يشترِ صناديق؛ هو فقط يحدد أن سعر الصندوق 5.تحتاج إلى إضافة زوج مفتاح وقيمة جديد إلى قاموس.
حدد القاموس والمفتاح والقيمة.
الثلاثة موجودون بالفعل في الكود المعطى.
القيمة هي التكلفة الإجمالية لذلك العنصر: الكمية مضروبة في السعر.
أي
quantities[item] * prices[item].القاموس هو الشيء الذي تنشئه هذه الدالة وتبنيه ثم تعيده.
أي
totals.لاحظ أن
'apple'مفتاح في القواميس الثلاثة في هذا الاختبار.أي القواميس
quantitiesوpricesوtotals.
ممتاز! لنرجع إلى مثال الترجمة.
لنفترض أن لدينا قاموسًا من الإنجليزية إلى الفرنسية، وقاموسًا آخر من الفرنسية إلى الألمانية. استخدمهما لإنشاء قاموس جديد من الإنجليزية إلى الألمانية:
def make_english_to_german(english_to_french, french_to_german):
...
check_result(
make_english_to_german(
{'apple': 'pomme', 'box': 'boite'},
{'pomme': 'apfel', 'boite': 'kasten'},
),
{'apple': 'apfel', 'box': 'kasten'},
)
أنشئ قاموسًا فارغًا، ومرّ على الكلمات الإنجليزية في القاموس الأول. قيمة الكلمة الإنجليزية في القاموس الأول هي الكلمة الفرنسية، وهذه الكلمة الفرنسية هي مفتاح في القاموس الثاني، ومنه تحصل على الكلمة الألمانية. أضف النتيجة إلى القاموس الجديد ثم أعده في النهاية.
تحتاج إلى إنشاء قاموس جديد وملئه بأزواج مفاتيح وقيم اعتمادًا على قاموسي الإدخال.
رأيت كودًا يفعل ذلك من قبل.
تحديدًا في الخطوة السابقة. البنية العامة المطلوبة تشبه
total_cost_per_item.ابدأ بإنشاء قاموس فارغ جديد.
أعد القاموس في النهاية، ثم اكتب الكود بين الإنشاء والإرجاع.
تحتاج إلى حلقة
for.السطر
totals[item] = quantities[item] * prices[item]من الخطوة السابقة قريب مما تحتاج إليه.لا تحتاج إلى الضرب بـ
*، والأسماء مختلفة، وهناك فرق آخر في المنطق.فكر في المفاتيح والقيم التي يجب أن يحتوي عليها القاموس الجديد.
المفاتيح يجب أن تكون كلمات إنجليزية، لذا تأتي من القاموس الأول.
القيم يجب أن تكون كلمات ألمانية، لذا تأتي من القاموس الثاني.
بالتحديد، مفاتيح قاموسك هي مفاتيح القاموس الأول.
وقيم قاموسك هي قيم القاموس الثاني.
وماذا عن قيم القاموس الأول ومفاتيح القاموس الثاني؟ لهما دور مهم.
انظر إلى الكلمتين الفرنسيتين
'pomme'و'boite'في الاختبار.قيم قاموس الإدخال الأول هي مفاتيح قاموس الإدخال الثاني.
عمل رائع!
اكتب الآن دالة تأخذ قاموسًا وتعيد قاموسًا جديدًا بعد تبديل المفاتيح والقيم؛ أي يتحول الزوج a: b إلى b: a:
def swap_keys_values(d):
...
check_result(
swap_keys_values({'apple': 'pomme', 'box': 'boite'}),
{'pomme': 'apple', 'boite': 'box'},
)
لا تعدّل القاموس الأصلي d. أنشئ قاموسًا فارغًا جديدًا، ومرّ على مفاتيح d. لكل مفتاح، احصل على قيمته، ثم استخدم هذه القيمة كمفتاح جديد واجعل المفتاح القديم هو القيمة الجديدة.
لا تعدّل قاموس الإدخال
d.تحتاج إلى إنشاء قاموس جديد وملئه بأزواج مفاتيح وقيم اعتمادًا على قاموس الإدخال.
فعلت ذلك في التمرين السابق. البنية العامة تشبه
make_english_to_german.الأمر أبسط في الحقيقة، حتى لو بدا غريبًا.
ابدأ بقاموس فارغ جديد، وأعده في النهاية، وضع بينهما حلقة
for.فكر في المفاتيح والقيم التي يجب أن يحتوي عليها القاموس الجديد.
لا يوجد سوى شيء واحد منطقي يمكنك الدوران عليه.
استخدم كل مفتاح في قاموس الإدخال
dللوصول إلى قيمته المقابلة.
ممتاز!
لكن من المهم أن تعرف أين يمكن أن تفشل فكرة تبديل المفاتيح والقيم. كما يمكن أن يكون لمنتجين في المتجر السعر نفسه، يمكن لكلمتين إنجليزيتين أن تكون لهما الترجمة الفرنسية نفسها.
إذا احتوى القاموس الأصلي على قيم مكررة، فماذا يحدث عندما تجعل هذه القيم مفاتيح؟ مفاتيح القاموس يجب أن تكون فريدة، لذلك ستضيع بعض البيانات.
مثلًا، الكلمة الفرنسية 'avocat' قد تعني avocado أو lawyer. من السهل ترجمة كل كلمة إنجليزية إلى الفرنسية، لكن عند رؤية 'avocat' وحدها لا نعرف أي معنى إنجليزي كان المقصود.
حاول توقع ما سيطبعه الكود التالي قبل تشغيله:
def swap_keys_values(d):
new_dict = {}
for key in d:
new_dict[d[key]] = key
return new_dict
print(swap_keys_values({'apple': 'pomme', 'avocado': 'avocat', 'lawyer': 'avocat'}))
print(swap_keys_values({'apple': 'pomme', 'lawyer': 'avocat', 'avocado': 'avocat'}))
تعتمد النتيجة على ترتيب المفاتيح في القاموس الأصلي. إذا لم يكن السبب واضحًا، فتتبّع تنفيذ الكود خطوة بخطوة وراقب متى تُكتب كل قيمة داخل القاموس الجديد.
ومع ذلك توجد حالات كثيرة تستطيع فيها التأكد من أن قيم القاموس الأصلية فريدة، وعندها يكون «عكس» القاموس منطقيًا. رأينا سابقًا هذا المثال:
def substitute(string, d):
result = ""
for letter in string:
result += d[letter]
return result
plaintext = 'helloworld'
encrypted = 'qpeefifmez'
letters = {'h': 'q', 'e': 'p', 'l': 'e', 'o': 'f', 'w': 'i', 'r': 'm', 'd': 'z'}
reverse = {'q': 'h', 'p': 'e', 'e': 'l', 'f': 'o', 'i': 'w', 'm': 'r', 'z': 'd'}
check_result(substitute(plaintext, letters), encrypted)
check_result(substitute(encrypted, reverse), plaintext)
والآن نستطيع إنشاء reverse تلقائيًا:
reverse = swap_keys_values(letters)
لكي ينجح هذا يجب أن تكون كل القيم في letters فريدة. إذا استُبدل كل من 'h' و'j' بالقيمة 'q' أثناء التشفير، فلن توجد طريقة عند فك التشفير لمعرفة هل 'qpeef' كانت أصلًا 'hello' أم 'jello'.
تهانينا! وصلت إلى نهاية الجزء المتاح حاليًا من الدورة. سيُضاف المزيد لاحقًا.