From 4e88cb6b7cc708489a0554e9fd6a5f11756d35cc Mon Sep 17 00:00:00 2001 From: Alex Hall Date: Sun, 30 Mar 2025 16:25:09 +0200 Subject: [PATCH 1/3] CreatingKeyValuePairs draft --- core/chapters/c12_dictionaries.py | 393 +++++- tests/golden_files/en/test_transcript.json | 209 +++ translations/english.po | 1216 ++++++++++++++++- .../locales/en/LC_MESSAGES/futurecoder.mo | Bin 297007 -> 308487 bytes 4 files changed, 1802 insertions(+), 16 deletions(-) diff --git a/core/chapters/c12_dictionaries.py b/core/chapters/c12_dictionaries.py index 6b70b08c..7cba16e2 100644 --- a/core/chapters/c12_dictionaries.py +++ b/core/chapters/c12_dictionaries.py @@ -2,17 +2,14 @@ import ast import random from collections import Counter -from typing import List, Dict +from copy import deepcopy +from typing import Dict, List from core import translation as t from core.exercises import assert_equal from core.exercises import generate_string, generate_dict -from core.text import ( - ExerciseStep, - Page, - Step, - VerbatimStep, -) +from core.text import Page, VerbatimStep, ExerciseStep, Step +from core.utils import returns_stdout, wrap_solution # Similar to word_must_be_hello @@ -668,3 +665,385 @@ def print_words(words): final_text = """ Congratulations! You've reached the end of the course so far. More is on the way! """ + # TODO + + +class CreatingKeyValuePairs(Page): + title = "Creating Key-Value Pairs" + + class list_append_reminder(VerbatimStep): + """ + Now we'll learn how to add key-value pairs to a dictionary, + e.g. so that we can keep track of what the customer is buying. + Before looking at dictionaries, let's remind ourselves how to add items to a list. Run this program: + + __copyable__ + __program_indented__ + """ + + def program(self): + cart = [] + cart.append('dog') + cart.append('box') + print(cart) + + class list_assign_reminder(VerbatimStep): + """ + Pretty simple. We can also change the value at an index, replacing it with a different one: + + __copyable__ + __program_indented__ + """ + predicted_output_choices = [ + "['dog', 'box']", + "['box', 'cat']", + "['dog', 'cat']", + ] + + def program(self): + cart = ['dog', 'cat'] + cart[1] = 'box' + print(cart) + + class list_assign_invalid(VerbatimStep): + """ + What if we used that idea to create our list in the first place? + We know we want a list where `cart[0]` is `'dog'` and `cart[1]` is `'box'`, so let's just say that: + + __copyable__ + __program_indented__ + """ + correct_output = "Error" # This program raises an IndexError + + def program(self): + cart = [] + cart[0] = 'dog' + cart[1] = 'box' + print(cart) + + class dict_assignment_valid(VerbatimStep): + """ + Sorry, that's not allowed. For lists, subscript assignment only works for existing valid indices. + But that's not true for dictionaries! Try this: + + __copyable__ + __program_indented__ + + Note that `{}` means an empty dictionary, i.e. a dictionary with no key-value pairs. + This is similar to `[]` meaning an empty list or `""` meaning an empty string. + """ + predicted_output_choices = [ + "{}", + "{'dog': 5000000}", + "{'box': 2}", + "{'dog': 5000000, 'box': 2}", + "{'box': 2, 'dog': 5000000}", # Order might vary, though CPython 3.7+ preserves insertion order + ] + + def program(self): + quantities = {} + quantities['dog'] = 5000000 + quantities['box'] = 2 + print(quantities) + + class buy_quantity_exercise(ExerciseStep): + """ + That's exactly what we need. When the customer says they want 5 million boxes, + we can just put that information directly into our dictionary. So as an exercise, let's make a generic version of that. + Write a function `buy_quantity(quantities)` which calls `input()` twice to get an item name and quantity from the user + and assigns them in the `quantities` dictionary. Here's some starting code: + + __copyable__ + def buy_quantity(quantities): + print('Item:') + item = input() + print('Quantity:') + ... + + def test(): + quantities = {} + buy_quantity(quantities) + print(quantities) + buy_quantity(quantities) + print(quantities) + + test() + + and an example of how a session should look: + + Item: + dog + Quantity: + 5000000 + {'dog': 5000000} + Item: + box + Quantity: + 2 + {'dog': 5000000, 'box': 2} + + Note that `buy_quantity` should *modify* the dictionary that's passed in, and doesn't need to return anything. + You can assume that the user will enter a valid integer for the quantity. + """ + requirements = "Your function should modify the `quantities` argument. It doesn't need to `return` or `print` anything." + no_returns_stdout = True # The function itself doesn't print/return, the test harness does + + hints = """ + The function needs to get two inputs from the user: the item name and the quantity. + The item name is already stored in the `item` variable. You need to get the quantity similarly. + Remember that `input()` returns a string. The quantity needs to be stored as a number (`int`). + How do you convert a string to an integer? + Once you have the `item` (string) and the quantity (integer), you need to add them to the `quantities` dictionary. + Use the dictionary assignment syntax you just learned: `dictionary[key] = value`. + What should be the key and what should be the value in this case? + """ + + def solution(self): + def buy_quantity(quantities: Dict[str, int]): + print('Item:') + item = input() + print('Quantity:') + quantity_str = input() + quantities[item] = int(quantity_str) + return buy_quantity + + @classmethod + def wrap_solution(cls, func): + @returns_stdout + @wrap_solution(func) + def wrapper(**kwargs): + quantities_name = t.get_code_bit("quantities") + quantities = kwargs[quantities_name] = deepcopy(kwargs[quantities_name]) + + func(**kwargs) + print(quantities) + return wrapper + + @classmethod + def generate_inputs(cls): + return { + "stdin_input": [generate_string(5), str(random.randint(1, 10))], + "quantities": generate_dict(str, int), + } + + tests = [ + ( + dict( + quantities={}, + stdin_input=[ + "dog", "5000000", + ] + ), + """\ +Item: + +Quantity: + +{'dog': 5000000} + """ + ), + ( + dict( + quantities={'dog': 5000000}, + stdin_input=[ + "box", "2", + ] + ), + """\ +Item: + +Quantity: + +{'dog': 5000000, 'box': 2} + """ + ), + ] + + class total_cost_per_item_exercise(ExerciseStep): + """ + Well done! + + Next exercise: earlier we defined a function `total_cost(quantities, prices)` which returned a single number + with a grand total of all the items in the cart. Now let's make a function `total_cost_per_item(quantities, prices)` + which returns a new dictionary with the total cost for each item: + + __copyable__ + def total_cost_per_item(quantities, prices): + totals = {} + for item in quantities: + ... = quantities[item] * prices[item] + return totals + + assert_equal( + total_cost_per_item({'apple': 2}, {'apple': 3, 'box': 5}), + {'apple': 6}, + ) + + assert_equal( + total_cost_per_item({'dog': 5000000, 'box': 2}, {'dog': 100, 'box': 5}), + {'dog': 500000000, 'box': 10}, + ) + """ + hints = """ + You need to iterate through the items in the `quantities` dictionary. + For each `item`, calculate the total cost for that item (quantity * price). + Store this calculated cost in the `totals` dictionary. + The key for the `totals` dictionary should be the `item` name. + Use the dictionary assignment syntax: `totals[item] = calculated_cost`. + Make sure this assignment happens *inside* the loop. + The function should return the `totals` dictionary after the loop finishes. + """ + + def solution(self): + def total_cost_per_item(quantities: Dict[str, int], prices: Dict[str, int]): + totals = {} + for item in quantities: + totals[item] = quantities[item] * prices[item] + return totals + return total_cost_per_item + + tests = [ + (({'apple': 2}, {'apple': 3, 'box': 5}), {'apple': 6}), + (({'dog': 5000000, 'box': 2}, {'dog': 100, 'box': 5}), {'dog': 500000000, 'box': 10}), + (({'pen': 5, 'pencil': 10}, {'pen': 1, 'pencil': 0.5, 'eraser': 2}), {'pen': 5, 'pencil': 5.0}), + (({}, {'apple': 1}), {}), + ] + + @classmethod + def generate_inputs(cls): + prices = generate_dict(str, int) + quantities = {k: random.randint(1, 10) for k in prices if random.choice([True, False])} + return {"quantities": quantities, "prices": prices} + + class make_english_to_german_exercise(ExerciseStep): + """ + Perfect! This is like having a nice receipt full of useful information. + + Let's come back to the example of using dictionaries for translation. Suppose we have one dictionary + for translating from English to French, and another for translating from French to German. + Let's use that to create a dictionary that translates from English to German: + + __copyable__ + def make_english_to_german(english_to_french, french_to_german): + ... + + assert_equal( + make_english_to_german( + {'apple': 'pomme', 'box': 'boite'}, + {'pomme': 'apfel', 'boite': 'kasten'}, + ), + {'apple': 'apfel', 'box': 'kasten'}, + ) + """ + parsons_solution = True + + hints = """ + You need to create a new empty dictionary, let's call it `english_to_german`. + Iterate through the keys (English words) of the `english_to_french` dictionary. + Inside the loop, for each `english` word: + 1. Find the corresponding French word using `english_to_french`. + 2. Use that French word as a key to find the German word in `french_to_german`. + 3. Add the `english` word as a key and the `german` word as the value to your new `english_to_german` dictionary. + After the loop, return the `english_to_german` dictionary. + """ + + def solution(self): + def make_english_to_german(english_to_french: Dict[str, str], french_to_german: Dict[str, str]): + english_to_german = {} + for english in english_to_french: + french = english_to_french[english] + german = french_to_german[french] + english_to_german[english] = german + return english_to_german + return make_english_to_german + + tests = [ + (({'apple': 'pomme', 'box': 'boite'}, {'pomme': 'apfel', 'boite': 'kasten'}), + {'apple': 'apfel', 'box': 'kasten'}), + (({'one': 'un', 'two': 'deux', 'three': 'trois'}, {'un': 'eins', 'deux': 'zwei', 'trois': 'drei'}), + {'one': 'eins', 'two': 'zwei', 'three': 'drei'}), + (({}, {}), {}), + ] + + @classmethod + def generate_inputs(cls): + english_to_french = generate_dict(str, str) + french_to_german = {v: generate_string() for v in english_to_french.values()} + return {"english_to_french": english_to_french, "french_to_german": french_to_german} + + class swap_keys_values_exercise(ExerciseStep): + """ + Great job! + + Of course, language isn't so simple, and there are many ways that using a dictionary like this could go wrong. + So...let's do something even worse! Write a function which takes a dictionary and swaps the keys and values, + so `a: b` becomes `b: a`. + + __copyable__ + def swap_keys_values(d): + ... + + assert_equal( + swap_keys_values({'apple': 'pomme', 'box': 'boite'}), + {'pomme': 'apple', 'boite': 'box'}, + ) + """ + hints = """ + Create a new empty dictionary to store the result. + Iterate through the keys of the input dictionary `d`. + Inside the loop, for each `key`: + 1. Get the corresponding `value` from `d`. + 2. Add an entry to the new dictionary where the *key* is the original `value` and the *value* is the original `key`. + Return the new dictionary after the loop. + """ + + def solution(self): + def swap_keys_values(d: Dict[str, str]): + new_dict = {} + for key in d: + value = d[key] + new_dict[value] = key + return new_dict + return swap_keys_values + + tests = [ + (({'apple': 'pomme', 'box': 'boite'},), {'pomme': 'apple', 'boite': 'box'}), + (({'a': 1, 'b': 2},), {1: 'a', 2: 'b'}), + (({10: 'x', 20: 'y'},), {'x': 10, 'y': 20}), + (({},), {}), + ] + + final_text = """ +Magnificent! + +Jokes aside, it's important to remember how exactly this can go wrong. Just like multiple items in the store +can have the same price, multiple words in English can have the same translation in French. If the original dictionary +has duplicate *values*, what happens when you try to swap keys and values? Since dictionary keys must be unique, +some data will be lost. + +But there are many situations where you can be sure that the values in a dictionary *are* unique and that this +'inversion' makes sense. For example, we saw this code [earlier in the chapter](#UsingDictionariesInPractice): + + __copyable__ + __no_auto_translate__ + 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'} + assert_equal(substitute(plaintext, letters), encrypted) + assert_equal(substitute(encrypted, reverse), plaintext) + +Now we can construct the `reverse` dictionary automatically: + + reverse = swap_keys_values(letters) + +For this to work, we just have to make sure that all the values in `letters` are unique. +Otherwise it would be impossible to decrypt messages properly. If both `'h'` and `'j'` got replaced with `'q'` +during encryption, there would be no way to know whether `'qpeef'` means `'hello'` or `'jello'`! +""" diff --git a/tests/golden_files/en/test_transcript.json b/tests/golden_files/en/test_transcript.json index 4ba82422..47ed4659 100644 --- a/tests/golden_files/en/test_transcript.json +++ b/tests/golden_files/en/test_transcript.json @@ -7228,5 +7228,214 @@ ] }, "step": "nested_dictionaries" + }, + { + "get_solution": "program", + "page": "Creating Key-Value Pairs", + "program": [ + "cart = []", + "cart.append('dog')", + "cart.append('box')", + "print(cart)" + ], + "response": { + "passed": true, + "result": [ + { + "text": "['dog', 'box']\n", + "type": "stdout" + } + ] + }, + "step": "list_append_reminder" + }, + { + "get_solution": "program", + "page": "Creating Key-Value Pairs", + "program": [ + "cart = ['dog', 'cat']", + "cart[1] = 'box'", + "print(cart)" + ], + "response": { + "passed": true, + "prediction": { + "answer": "['dog', 'box']", + "choices": [ + "['dog', 'box']", + "['box', 'cat']", + "['dog', 'cat']", + "Error" + ] + }, + "result": [ + { + "text": "['dog', 'box']\n", + "type": "stdout" + } + ] + }, + "step": "list_assign_reminder" + }, + { + "get_solution": "program", + "page": "Creating Key-Value Pairs", + "program": [ + "cart = []", + "cart[0] = 'dog'", + "cart[1] = 'box'", + "print(cart)" + ], + "response": { + "passed": true, + "result": [ + { + "data": [ + { + "didyoumean": [], + "exception": { + "message": "list assignment index out of range", + "type": "IndexError" + }, + "frames": [ + { + "filename": "/my_program.py", + "lineno": 2, + "lines": [ + { + "is_current": true, + "lineno": 2, + "text": "cart[0] = 'dog'", + "type": "line" + } + ], + "name": "", + "type": "frame", + "variables": [ + { + "name": "cart\n", + "value": "[]\n" + } + ] + } + ], + "friendly": "

An IndexError occurs when you try to get an item from a list,\na tuple, or a similar object (sequence), and use an index which\ndoes not exist; typically, this happens because the index you give\nis greater than the length of the sequence.

\n

You have tried to assign a value to index 0 of cart,\na list which contains no item.

", + "tail": "" + } + ], + "text": [ + "Traceback (most recent call last):", + " File \"/my_program.py\", line 2, in ", + " 1 | cart = []", + "--> 2 | cart[0] = 'dog'", + " ^^^^^^^", + "cart = []", + "", + "IndexError: list assignment index out of range" + ], + "type": "traceback" + } + ] + }, + "step": "list_assign_invalid" + }, + { + "get_solution": "program", + "page": "Creating Key-Value Pairs", + "program": [ + "quantities = {}", + "quantities['dog'] = 5000000", + "quantities['box'] = 2", + "print(quantities)" + ], + "response": { + "passed": true, + "prediction": { + "answer": "{'dog': 5000000, 'box': 2}", + "choices": [ + "{}", + "{'dog': 5000000}", + "{'box': 2}", + "{'dog': 5000000, 'box': 2}", + "{'box': 2, 'dog': 5000000}", + "Error" + ] + }, + "result": [ + { + "text": "{'dog': 5000000, 'box': 2}\n", + "type": "stdout" + } + ] + }, + "step": "dict_assignment_valid" + }, + { + "get_solution": "program", + "page": "Creating Key-Value Pairs", + "program": [ + "def buy_quantity(quantities):", + " print('Item:')", + " item = input()", + " print('Quantity:')", + " quantity_str = input()", + " quantities[item] = int(quantity_str)" + ], + "response": { + "passed": true, + "result": [] + }, + "step": "buy_quantity_exercise" + }, + { + "get_solution": "program", + "page": "Creating Key-Value Pairs", + "program": [ + "def total_cost_per_item(quantities, prices):", + " totals = {}", + " for item in quantities:", + " totals[item] = quantities[item] * prices[item]", + " return totals" + ], + "response": { + "passed": true, + "result": [] + }, + "step": "total_cost_per_item_exercise" + }, + { + "get_solution": "program", + "page": "Creating Key-Value Pairs", + "program": [ + "def make_english_to_german(english_to_french, french_to_german):", + " english_to_german = {}", + " for english in english_to_french:", + " french = english_to_french[english]", + " german = french_to_german[french]", + " english_to_german[english] = german", + " return english_to_german" + ], + "response": { + "passed": true, + "result": [] + }, + "step": "make_english_to_german_exercise" + }, + { + "get_solution": "program", + "page": "Creating Key-Value Pairs", + "program": [ + "def swap_keys_values(d):", + " new_dict = {}", + " for key in d:", + " value = d[key]", + " new_dict[value] = key", + " return new_dict" + ], + "response": { + "passed": true, + "result": [] + }, + "step": "swap_keys_values_exercise" } ] \ No newline at end of file diff --git a/translations/english.po b/translations/english.po index ea379858..ca2e6007 100644 --- a/translations/english.po +++ b/translations/english.po @@ -2512,6 +2512,36 @@ msgstr "'Hello there'" msgid "code_bits.'Hello'" msgstr "'Hello'" +#. https://poeditor.com/projects/view_terms?id=490053&search=pages.CreatingKeyValuePairs.steps.buy_quantity_exercise +#. +#. def buy_quantity(quantities): +#. print('Item:') +#. item = input() +#. print('Quantity:') +#. quantity_str = input() +#. quantities[item] = int(quantity_str) +#. +#. ------ +#. +#. https://poeditor.com/projects/view_terms?id=490053&search=pages.CreatingKeyValuePairs.steps.buy_quantity_exercise.text +#. +#. def buy_quantity(quantities): +#. print('Item:') +#. item = input() +#. print('Quantity:') +#. ... +#. +#. def test(): +#. quantities = {} +#. buy_quantity(quantities) +#. print(quantities) +#. buy_quantity(quantities) +#. print(quantities) +#. +#. test() +msgid "code_bits.'Item:'" +msgstr "'Item:'" + #. https://poeditor.com/projects/view_terms?id=490053&search=pages.IfAndElse.steps.first_if_else #. #. condition = True @@ -2572,6 +2602,36 @@ msgstr "'One more exercise, and then you can relax.'" msgid "code_bits.'Python'" msgstr "'Python'" +#. https://poeditor.com/projects/view_terms?id=490053&search=pages.CreatingKeyValuePairs.steps.buy_quantity_exercise +#. +#. def buy_quantity(quantities): +#. print('Item:') +#. item = input() +#. print('Quantity:') +#. quantity_str = input() +#. quantities[item] = int(quantity_str) +#. +#. ------ +#. +#. https://poeditor.com/projects/view_terms?id=490053&search=pages.CreatingKeyValuePairs.steps.buy_quantity_exercise.text +#. +#. def buy_quantity(quantities): +#. print('Item:') +#. item = input() +#. print('Quantity:') +#. ... +#. +#. def test(): +#. quantities = {} +#. buy_quantity(quantities) +#. print(quantities) +#. buy_quantity(quantities) +#. print(quantities) +#. +#. test() +msgid "code_bits.'Quantity:'" +msgstr "'Quantity:'" + #. https://poeditor.com/projects/view_terms?id=490053&search=pages.Types.steps.fixing_type_errors_with_conversion #. #. number = '1' @@ -3185,6 +3245,21 @@ msgstr "'abcqwe'" msgid "code_bits.'aeiou'" msgstr "'aeiou'" +#. https://poeditor.com/projects/view_terms?id=490053&search=pages.CreatingKeyValuePairs.steps.make_english_to_german_exercise.text +#. +#. def make_english_to_german(english_to_french, french_to_german): +#. ... +#. +#. assert_equal( +#. make_english_to_german( +#. {'apple': 'pomme', 'box': 'boite'}, +#. {'pomme': 'apfel', 'boite': 'kasten'}, +#. ), +#. {'apple': 'apfel', 'box': 'kasten'}, +#. ) +#. +#. ------ +#. #. https://poeditor.com/projects/view_terms?id=490053&search=pages.DictionaryKeysAndValues.steps.english_to_german.text #. #. def print_words(french, german): @@ -3221,6 +3296,33 @@ msgstr "'aeiou'" msgid "code_bits.'apfel'" msgstr "'apfel'" +#. https://poeditor.com/projects/view_terms?id=490053&search=pages.CreatingKeyValuePairs.steps.make_english_to_german_exercise.text +#. +#. def make_english_to_german(english_to_french, french_to_german): +#. ... +#. +#. assert_equal( +#. make_english_to_german( +#. {'apple': 'pomme', 'box': 'boite'}, +#. {'pomme': 'apfel', 'boite': 'kasten'}, +#. ), +#. {'apple': 'apfel', 'box': 'kasten'}, +#. ) +#. +#. ------ +#. +#. https://poeditor.com/projects/view_terms?id=490053&search=pages.CreatingKeyValuePairs.steps.swap_keys_values_exercise.text +#. +#. def swap_keys_values(d): +#. ... +#. +#. assert_equal( +#. swap_keys_values({'apple': 'pomme', 'box': 'boite'}), +#. {'pomme': 'apple', 'boite': 'box'}, +#. ) +#. +#. ------ +#. #. https://poeditor.com/projects/view_terms?id=490053&search=pages.DictionaryKeysAndValues.steps.cleanup_shopping_cart.text #. #. def total_cost(quantities, prices): @@ -3408,6 +3510,33 @@ msgstr "'are'" msgid "code_bits.'bc'" msgstr "'bc'" +#. https://poeditor.com/projects/view_terms?id=490053&search=pages.CreatingKeyValuePairs.steps.make_english_to_german_exercise.text +#. +#. def make_english_to_german(english_to_french, french_to_german): +#. ... +#. +#. assert_equal( +#. make_english_to_german( +#. {'apple': 'pomme', 'box': 'boite'}, +#. {'pomme': 'apfel', 'boite': 'kasten'}, +#. ), +#. {'apple': 'apfel', 'box': 'kasten'}, +#. ) +#. +#. ------ +#. +#. https://poeditor.com/projects/view_terms?id=490053&search=pages.CreatingKeyValuePairs.steps.swap_keys_values_exercise.text +#. +#. def swap_keys_values(d): +#. ... +#. +#. assert_equal( +#. swap_keys_values({'apple': 'pomme', 'box': 'boite'}), +#. {'pomme': 'apple', 'boite': 'box'}, +#. ) +#. +#. ------ +#. #. https://poeditor.com/projects/view_terms?id=490053&search=pages.DictionaryKeysAndValues.steps.english_to_french.text #. #. def print_words(french): @@ -3459,6 +3588,68 @@ msgstr "'bc'" msgid "code_bits.'boite'" msgstr "'boite'" +#. https://poeditor.com/projects/view_terms?id=490053&search=pages.CreatingKeyValuePairs.steps.dict_assignment_valid +#. +#. quantities = {} +#. quantities['dog'] = 5000000 +#. quantities['box'] = 2 +#. print(quantities) +#. +#. ------ +#. +#. https://poeditor.com/projects/view_terms?id=490053&search=pages.CreatingKeyValuePairs.steps.list_append_reminder +#. +#. cart = [] +#. cart.append('dog') +#. cart.append('box') +#. print(cart) +#. +#. ------ +#. +#. https://poeditor.com/projects/view_terms?id=490053&search=pages.CreatingKeyValuePairs.steps.list_assign_invalid +#. +#. cart = [] +#. cart[0] = 'dog' +#. cart[1] = 'box' +#. print(cart) +#. +#. ------ +#. +#. https://poeditor.com/projects/view_terms?id=490053&search=pages.CreatingKeyValuePairs.steps.list_assign_reminder +#. +#. cart = ['dog', 'cat'] +#. cart[1] = 'box' +#. print(cart) +#. +#. ------ +#. +#. https://poeditor.com/projects/view_terms?id=490053&search=pages.CreatingKeyValuePairs.steps.make_english_to_german_exercise.text +#. +#. def make_english_to_german(english_to_french, french_to_german): +#. ... +#. +#. assert_equal( +#. make_english_to_german( +#. {'apple': 'pomme', 'box': 'boite'}, +#. {'pomme': 'apfel', 'boite': 'kasten'}, +#. ), +#. {'apple': 'apfel', 'box': 'kasten'}, +#. ) +#. +#. ------ +#. +#. https://poeditor.com/projects/view_terms?id=490053&search=pages.CreatingKeyValuePairs.steps.swap_keys_values_exercise.text +#. +#. def swap_keys_values(d): +#. ... +#. +#. assert_equal( +#. swap_keys_values({'apple': 'pomme', 'box': 'boite'}), +#. {'pomme': 'apple', 'boite': 'box'}, +#. ) +#. +#. ------ +#. #. https://poeditor.com/projects/view_terms?id=490053&search=pages.DictionaryKeysAndValues.steps.cleanup_shopping_cart.text #. #. def total_cost(quantities, prices): @@ -3582,6 +3773,14 @@ msgstr "'boite'" msgid "code_bits.'box'" msgstr "'box'" +#. https://poeditor.com/projects/view_terms?id=490053&search=pages.CreatingKeyValuePairs.steps.list_assign_reminder +#. +#. cart = ['dog', 'cat'] +#. cart[1] = 'box' +#. print(cart) +#. +#. ------ +#. #. https://poeditor.com/projects/view_terms?id=490053&search=pages.DictionaryKeysAndValues.steps.cleanup_shopping_cart.text #. #. def total_cost(quantities, prices): @@ -3723,6 +3922,41 @@ msgstr "'de'" msgid "code_bits.'def'" msgstr "'def'" +#. https://poeditor.com/projects/view_terms?id=490053&search=pages.CreatingKeyValuePairs.steps.dict_assignment_valid +#. +#. quantities = {} +#. quantities['dog'] = 5000000 +#. quantities['box'] = 2 +#. print(quantities) +#. +#. ------ +#. +#. https://poeditor.com/projects/view_terms?id=490053&search=pages.CreatingKeyValuePairs.steps.list_append_reminder +#. +#. cart = [] +#. cart.append('dog') +#. cart.append('box') +#. print(cart) +#. +#. ------ +#. +#. https://poeditor.com/projects/view_terms?id=490053&search=pages.CreatingKeyValuePairs.steps.list_assign_invalid +#. +#. cart = [] +#. cart[0] = 'dog' +#. cart[1] = 'box' +#. print(cart) +#. +#. ------ +#. +#. https://poeditor.com/projects/view_terms?id=490053&search=pages.CreatingKeyValuePairs.steps.list_assign_reminder +#. +#. cart = ['dog', 'cat'] +#. cart[1] = 'box' +#. print(cart) +#. +#. ------ +#. #. https://poeditor.com/projects/view_terms?id=490053&search=pages.DictionaryKeysAndValues.steps.cleanup_shopping_cart.text #. #. def total_cost(quantities, prices): @@ -4102,6 +4336,21 @@ msgstr "'is'" msgid "code_bits.'jklmn'" msgstr "'jklmn'" +#. https://poeditor.com/projects/view_terms?id=490053&search=pages.CreatingKeyValuePairs.steps.make_english_to_german_exercise.text +#. +#. def make_english_to_german(english_to_french, french_to_german): +#. ... +#. +#. assert_equal( +#. make_english_to_german( +#. {'apple': 'pomme', 'box': 'boite'}, +#. {'pomme': 'apfel', 'boite': 'kasten'}, +#. ), +#. {'apple': 'apfel', 'box': 'kasten'}, +#. ) +#. +#. ------ +#. #. https://poeditor.com/projects/view_terms?id=490053&search=pages.DictionaryKeysAndValues.steps.english_to_german.text #. #. def print_words(french, german): @@ -4220,6 +4469,33 @@ msgstr "'list'" msgid "code_bits.'on'" msgstr "'on'" +#. https://poeditor.com/projects/view_terms?id=490053&search=pages.CreatingKeyValuePairs.steps.make_english_to_german_exercise.text +#. +#. def make_english_to_german(english_to_french, french_to_german): +#. ... +#. +#. assert_equal( +#. make_english_to_german( +#. {'apple': 'pomme', 'box': 'boite'}, +#. {'pomme': 'apfel', 'boite': 'kasten'}, +#. ), +#. {'apple': 'apfel', 'box': 'kasten'}, +#. ) +#. +#. ------ +#. +#. https://poeditor.com/projects/view_terms?id=490053&search=pages.CreatingKeyValuePairs.steps.swap_keys_values_exercise.text +#. +#. def swap_keys_values(d): +#. ... +#. +#. assert_equal( +#. swap_keys_values({'apple': 'pomme', 'box': 'boite'}), +#. {'pomme': 'apple', 'boite': 'box'}, +#. ) +#. +#. ------ +#. #. https://poeditor.com/projects/view_terms?id=490053&search=pages.DictionaryKeysAndValues.steps.english_to_french.text #. #. def print_words(french): @@ -4374,6 +4650,30 @@ msgstr "'you'" msgid "code_bits.Hello" msgstr "Hello" +#. https://poeditor.com/projects/view_terms?id=490053&search=pages.CreatingKeyValuePairs.steps.dict_assignment_valid.text +#. +#. __program_indented__ +#. +#. ------ +#. +#. https://poeditor.com/projects/view_terms?id=490053&search=pages.CreatingKeyValuePairs.steps.list_append_reminder.text +#. +#. __program_indented__ +#. +#. ------ +#. +#. https://poeditor.com/projects/view_terms?id=490053&search=pages.CreatingKeyValuePairs.steps.list_assign_invalid.text +#. +#. __program_indented__ +#. +#. ------ +#. +#. https://poeditor.com/projects/view_terms?id=490053&search=pages.CreatingKeyValuePairs.steps.list_assign_reminder.text +#. +#. __program_indented__ +#. +#. ------ +#. #. https://poeditor.com/projects/view_terms?id=490053&search=pages.DictionaryKeysAndValues.steps.keys_are_iterable.text #. #. __program_indented__ @@ -4857,6 +5157,33 @@ msgstr "all_numbers" #. #. ------ #. +#. https://poeditor.com/projects/view_terms?id=490053&search=pages.CreatingKeyValuePairs.steps.make_english_to_german_exercise.text +#. +#. def make_english_to_german(english_to_french, french_to_german): +#. ... +#. +#. assert_equal( +#. make_english_to_german( +#. {'apple': 'pomme', 'box': 'boite'}, +#. {'pomme': 'apfel', 'boite': 'kasten'}, +#. ), +#. {'apple': 'apfel', 'box': 'kasten'}, +#. ) +#. +#. ------ +#. +#. https://poeditor.com/projects/view_terms?id=490053&search=pages.CreatingKeyValuePairs.steps.swap_keys_values_exercise.text +#. +#. def swap_keys_values(d): +#. ... +#. +#. assert_equal( +#. swap_keys_values({'apple': 'pomme', 'box': 'boite'}), +#. {'pomme': 'apple', 'boite': 'box'}, +#. ) +#. +#. ------ +#. #. https://poeditor.com/projects/view_terms?id=490053&search=pages.DictionaryKeysAndValues.steps.cleanup_shopping_cart.text #. #. def total_cost(quantities, prices): @@ -6422,6 +6749,36 @@ msgstr "board" msgid "code_bits.board_size" msgstr "board_size" +#. https://poeditor.com/projects/view_terms?id=490053&search=pages.CreatingKeyValuePairs.steps.buy_quantity_exercise +#. +#. def buy_quantity(quantities): +#. print('Item:') +#. item = input() +#. print('Quantity:') +#. quantity_str = input() +#. quantities[item] = int(quantity_str) +#. +#. ------ +#. +#. https://poeditor.com/projects/view_terms?id=490053&search=pages.CreatingKeyValuePairs.steps.buy_quantity_exercise.text +#. +#. def buy_quantity(quantities): +#. print('Item:') +#. item = input() +#. print('Quantity:') +#. ... +#. +#. def test(): +#. quantities = {} +#. buy_quantity(quantities) +#. print(quantities) +#. buy_quantity(quantities) +#. print(quantities) +#. +#. test() +msgid "code_bits.buy_quantity" +msgstr "buy_quantity" + #. https://poeditor.com/projects/view_terms?id=490053&search=pages.IntroducingNestedLoops.steps.crack_password_exercise #. #. letters = 'AB' @@ -6466,6 +6823,32 @@ msgstr "c3" msgid "code_bits.c4" msgstr "c4" +#. https://poeditor.com/projects/view_terms?id=490053&search=pages.CreatingKeyValuePairs.steps.list_append_reminder +#. +#. cart = [] +#. cart.append('dog') +#. cart.append('box') +#. print(cart) +#. +#. ------ +#. +#. https://poeditor.com/projects/view_terms?id=490053&search=pages.CreatingKeyValuePairs.steps.list_assign_invalid +#. +#. cart = [] +#. cart[0] = 'dog' +#. cart[1] = 'box' +#. print(cart) +#. +#. ------ +#. +#. https://poeditor.com/projects/view_terms?id=490053&search=pages.CreatingKeyValuePairs.steps.list_assign_reminder +#. +#. cart = ['dog', 'cat'] +#. cart[1] = 'box' +#. print(cart) +#. +#. ------ +#. #. https://poeditor.com/projects/view_terms?id=490053&search=pages.UsingDictionaries.steps.shopping_cart1 #. #. def total_cost(cart, prices): @@ -8612,6 +8995,57 @@ msgstr "doubles" msgid "code_bits.element" msgstr "element" +#. https://poeditor.com/projects/view_terms?id=490053&search=pages.CreatingKeyValuePairs.steps.make_english_to_german_exercise +#. +#. def make_english_to_german(english_to_french, french_to_german): +#. english_to_german = {} +#. for english in english_to_french: +#. french = english_to_french[english] +#. german = french_to_german[french] +#. english_to_german[english] = german +#. return english_to_german +msgid "code_bits.english" +msgstr "english" + +#. https://poeditor.com/projects/view_terms?id=490053&search=pages.CreatingKeyValuePairs.steps.make_english_to_german_exercise +#. +#. def make_english_to_german(english_to_french, french_to_german): +#. english_to_german = {} +#. for english in english_to_french: +#. french = english_to_french[english] +#. german = french_to_german[french] +#. english_to_german[english] = german +#. return english_to_german +#. +#. ------ +#. +#. https://poeditor.com/projects/view_terms?id=490053&search=pages.CreatingKeyValuePairs.steps.make_english_to_german_exercise.text +#. +#. def make_english_to_german(english_to_french, french_to_german): +#. ... +#. +#. assert_equal( +#. make_english_to_german( +#. {'apple': 'pomme', 'box': 'boite'}, +#. {'pomme': 'apfel', 'boite': 'kasten'}, +#. ), +#. {'apple': 'apfel', 'box': 'kasten'}, +#. ) +msgid "code_bits.english_to_french" +msgstr "english_to_french" + +#. https://poeditor.com/projects/view_terms?id=490053&search=pages.CreatingKeyValuePairs.steps.make_english_to_german_exercise +#. +#. def make_english_to_german(english_to_french, french_to_german): +#. english_to_german = {} +#. for english in english_to_french: +#. french = english_to_french[english] +#. german = french_to_german[french] +#. english_to_german[english] = german +#. return english_to_german +msgid "code_bits.english_to_german" +msgstr "english_to_german" + #. https://poeditor.com/projects/view_terms?id=490053&search=pages.IntroducingTicTacToe.steps.intro_row_winner #. #. def row_winner(board): @@ -10302,6 +10736,18 @@ msgstr "format_board" msgid "code_bits.found" msgstr "found" +#. https://poeditor.com/projects/view_terms?id=490053&search=pages.CreatingKeyValuePairs.steps.make_english_to_german_exercise +#. +#. def make_english_to_german(english_to_french, french_to_german): +#. english_to_german = {} +#. for english in english_to_french: +#. french = english_to_french[english] +#. german = french_to_german[french] +#. english_to_german[english] = german +#. return english_to_german +#. +#. ------ +#. #. https://poeditor.com/projects/view_terms?id=490053&search=pages.DictionaryKeysAndValues.steps.english_to_french #. #. def print_words(french): @@ -10374,6 +10820,33 @@ msgstr "found" msgid "code_bits.french" msgstr "french" +#. https://poeditor.com/projects/view_terms?id=490053&search=pages.CreatingKeyValuePairs.steps.make_english_to_german_exercise +#. +#. def make_english_to_german(english_to_french, french_to_german): +#. english_to_german = {} +#. for english in english_to_french: +#. french = english_to_french[english] +#. german = french_to_german[french] +#. english_to_german[english] = german +#. return english_to_german +#. +#. ------ +#. +#. https://poeditor.com/projects/view_terms?id=490053&search=pages.CreatingKeyValuePairs.steps.make_english_to_german_exercise.text +#. +#. def make_english_to_german(english_to_french, french_to_german): +#. ... +#. +#. assert_equal( +#. make_english_to_german( +#. {'apple': 'pomme', 'box': 'boite'}, +#. {'pomme': 'apfel', 'boite': 'kasten'}, +#. ), +#. {'apple': 'apfel', 'box': 'kasten'}, +#. ) +msgid "code_bits.french_to_german" +msgstr "french_to_german" + #. https://poeditor.com/projects/view_terms?id=490053&search=pages.IntroducingFstrings.steps.introduce_f_strings #. #. name = "Alice" @@ -10412,6 +10885,18 @@ msgstr "friend" msgid "code_bits.game_board" msgstr "game_board" +#. https://poeditor.com/projects/view_terms?id=490053&search=pages.CreatingKeyValuePairs.steps.make_english_to_german_exercise +#. +#. def make_english_to_german(english_to_french, french_to_german): +#. english_to_german = {} +#. for english in english_to_french: +#. french = english_to_french[english] +#. german = french_to_german[french] +#. english_to_german[english] = german +#. return english_to_german +#. +#. ------ +#. #. https://poeditor.com/projects/view_terms?id=490053&search=pages.DictionaryKeysAndValues.steps.english_to_german #. #. def print_words(french, german): @@ -10863,19 +11348,59 @@ msgstr "is_friend" msgid "code_bits.is_valid_percentage" msgstr "is_valid_percentage" -#. https://poeditor.com/projects/view_terms?id=490053&search=pages.DictionaryKeysAndValues.steps.cleanup_shopping_cart +#. https://poeditor.com/projects/view_terms?id=490053&search=pages.CreatingKeyValuePairs.steps.buy_quantity_exercise #. -#. def total_cost(quantities, prices): -#. result = 0 -#. for item in quantities: -#. price = prices[item] -#. quantity = quantities[item] -#. result += price * quantity -#. return result +#. def buy_quantity(quantities): +#. print('Item:') +#. item = input() +#. print('Quantity:') +#. quantity_str = input() +#. quantities[item] = int(quantity_str) #. #. ------ #. -#. https://poeditor.com/projects/view_terms?id=490053&search=pages.DictionaryKeysAndValues.steps.cleanup_shopping_cart.text +#. https://poeditor.com/projects/view_terms?id=490053&search=pages.CreatingKeyValuePairs.steps.buy_quantity_exercise.text +#. +#. def buy_quantity(quantities): +#. print('Item:') +#. item = input() +#. print('Quantity:') +#. ... +#. +#. def test(): +#. quantities = {} +#. buy_quantity(quantities) +#. print(quantities) +#. buy_quantity(quantities) +#. print(quantities) +#. +#. test() +#. +#. ------ +#. +#. https://poeditor.com/projects/view_terms?id=490053&search=pages.CreatingKeyValuePairs.steps.total_cost_per_item_exercise +#. +#. def total_cost_per_item(quantities, prices): +#. totals = {} +#. for item in quantities: +#. totals[item] = quantities[item] * prices[item] +#. return totals +#. +#. ------ +#. +#. https://poeditor.com/projects/view_terms?id=490053&search=pages.DictionaryKeysAndValues.steps.cleanup_shopping_cart +#. +#. def total_cost(quantities, prices): +#. result = 0 +#. for item in quantities: +#. price = prices[item] +#. quantity = quantities[item] +#. result += price * quantity +#. return result +#. +#. ------ +#. +#. https://poeditor.com/projects/view_terms?id=490053&search=pages.DictionaryKeysAndValues.steps.cleanup_shopping_cart.text #. #. def total_cost(quantities, prices): #. result = 0 @@ -11076,6 +11601,17 @@ msgstr "joined_row" msgid "code_bits.joined_rows" msgstr "joined_rows" +#. https://poeditor.com/projects/view_terms?id=490053&search=pages.CreatingKeyValuePairs.steps.swap_keys_values_exercise +#. +#. def swap_keys_values(d): +#. new_dict = {} +#. for key in d: +#. value = d[key] +#. new_dict[value] = key +#. return new_dict +#. +#. ------ +#. #. https://poeditor.com/projects/view_terms?id=490053&search=pages.DictionaryKeysAndValues.steps.keys_are_iterable #. #. quantities = {'apple': 1, 'cat': 10} @@ -11335,6 +11871,12 @@ msgstr "lengths" msgid "code_bits.letter" msgstr "letter" +#. https://poeditor.com/projects/view_terms?id=490053&search=pages.CreatingKeyValuePairs.steps.final_text.text +#. +#. reverse = swap_keys_values(letters) +#. +#. ------ +#. #. https://poeditor.com/projects/view_terms?id=490053&search=pages.IntroducingNestedLoops.steps.crack_password_exercise #. #. letters = 'AB' @@ -12113,6 +12655,33 @@ msgstr "make_board" msgid "code_bits.make_cube" msgstr "make_cube" +#. https://poeditor.com/projects/view_terms?id=490053&search=pages.CreatingKeyValuePairs.steps.make_english_to_german_exercise +#. +#. def make_english_to_german(english_to_french, french_to_german): +#. english_to_german = {} +#. for english in english_to_french: +#. french = english_to_french[english] +#. german = french_to_german[french] +#. english_to_german[english] = german +#. return english_to_german +#. +#. ------ +#. +#. https://poeditor.com/projects/view_terms?id=490053&search=pages.CreatingKeyValuePairs.steps.make_english_to_german_exercise.text +#. +#. def make_english_to_german(english_to_french, french_to_german): +#. ... +#. +#. assert_equal( +#. make_english_to_german( +#. {'apple': 'pomme', 'box': 'boite'}, +#. {'pomme': 'apfel', 'boite': 'kasten'}, +#. ), +#. {'apple': 'apfel', 'box': 'kasten'}, +#. ) +msgid "code_bits.make_english_to_german" +msgstr "make_english_to_german" + #. https://poeditor.com/projects/view_terms?id=490053&search=pages.IntroducingFstrings.steps.introduce_f_strings #. #. name = "Alice" @@ -12680,6 +13249,17 @@ msgstr "middle" msgid "code_bits.name" msgstr "name" +#. https://poeditor.com/projects/view_terms?id=490053&search=pages.CreatingKeyValuePairs.steps.swap_keys_values_exercise +#. +#. def swap_keys_values(d): +#. new_dict = {} +#. for key in d: +#. value = d[key] +#. new_dict[value] = key +#. return new_dict +msgid "code_bits.new_dict" +msgstr "new_dict" + #. https://poeditor.com/projects/view_terms?id=490053&search=pages.TheEqualityOperator.steps.if_equals_replacing_characters #. #. name = 'kesha' @@ -14640,6 +15220,16 @@ msgstr "present" msgid "code_bits.price" msgstr "price" +#. https://poeditor.com/projects/view_terms?id=490053&search=pages.CreatingKeyValuePairs.steps.total_cost_per_item_exercise +#. +#. def total_cost_per_item(quantities, prices): +#. totals = {} +#. for item in quantities: +#. totals[item] = quantities[item] * prices[item] +#. return totals +#. +#. ------ +#. #. https://poeditor.com/projects/view_terms?id=490053&search=pages.DictionaryKeysAndValues.steps.cleanup_shopping_cart #. #. def total_cost(quantities, prices): @@ -15268,6 +15858,55 @@ msgstr "printed" msgid "code_bits.quadruple" msgstr "quadruple" +#. https://poeditor.com/projects/view_terms?id=490053&search=pages.CreatingKeyValuePairs.steps.buy_quantity_exercise +#. +#. def buy_quantity(quantities): +#. print('Item:') +#. item = input() +#. print('Quantity:') +#. quantity_str = input() +#. quantities[item] = int(quantity_str) +#. +#. ------ +#. +#. https://poeditor.com/projects/view_terms?id=490053&search=pages.CreatingKeyValuePairs.steps.buy_quantity_exercise.text +#. +#. def buy_quantity(quantities): +#. print('Item:') +#. item = input() +#. print('Quantity:') +#. ... +#. +#. def test(): +#. quantities = {} +#. buy_quantity(quantities) +#. print(quantities) +#. buy_quantity(quantities) +#. print(quantities) +#. +#. test() +#. +#. ------ +#. +#. https://poeditor.com/projects/view_terms?id=490053&search=pages.CreatingKeyValuePairs.steps.dict_assignment_valid +#. +#. quantities = {} +#. quantities['dog'] = 5000000 +#. quantities['box'] = 2 +#. print(quantities) +#. +#. ------ +#. +#. https://poeditor.com/projects/view_terms?id=490053&search=pages.CreatingKeyValuePairs.steps.total_cost_per_item_exercise +#. +#. def total_cost_per_item(quantities, prices): +#. totals = {} +#. for item in quantities: +#. totals[item] = quantities[item] * prices[item] +#. return totals +#. +#. ------ +#. #. https://poeditor.com/projects/view_terms?id=490053&search=pages.DictionaryKeysAndValues.steps.cleanup_shopping_cart #. #. def total_cost(quantities, prices): @@ -15428,6 +16067,17 @@ msgstr "quantities" msgid "code_bits.quantity" msgstr "quantity" +#. https://poeditor.com/projects/view_terms?id=490053&search=pages.CreatingKeyValuePairs.steps.buy_quantity_exercise +#. +#. def buy_quantity(quantities): +#. print('Item:') +#. item = input() +#. print('Quantity:') +#. quantity_str = input() +#. quantities[item] = int(quantity_str) +msgid "code_bits.quantity_str" +msgstr "quantity_str" + #. https://poeditor.com/projects/view_terms?id=490053&search=pages.DictionaryKeysAndValues.steps.cleanup_shopping_cart #. #. def total_cost(quantities, prices): @@ -15581,6 +16231,12 @@ msgstr "quantity" msgid "code_bits.result" msgstr "result" +#. https://poeditor.com/projects/view_terms?id=490053&search=pages.CreatingKeyValuePairs.steps.final_text.text +#. +#. reverse = swap_keys_values(letters) +msgid "code_bits.reverse" +msgstr "reverse" + #. https://poeditor.com/projects/view_terms?id=490053&search=pages.IntroducingNestedLoops.steps.times_table_exercise #. #. for left in range(12): @@ -17961,6 +18617,35 @@ msgstr "super_secret_number" msgid "code_bits.surround" msgstr "surround" +#. https://poeditor.com/projects/view_terms?id=490053&search=pages.CreatingKeyValuePairs.steps.final_text.text +#. +#. reverse = swap_keys_values(letters) +#. +#. ------ +#. +#. https://poeditor.com/projects/view_terms?id=490053&search=pages.CreatingKeyValuePairs.steps.swap_keys_values_exercise +#. +#. def swap_keys_values(d): +#. new_dict = {} +#. for key in d: +#. value = d[key] +#. new_dict[value] = key +#. return new_dict +#. +#. ------ +#. +#. https://poeditor.com/projects/view_terms?id=490053&search=pages.CreatingKeyValuePairs.steps.swap_keys_values_exercise.text +#. +#. def swap_keys_values(d): +#. ... +#. +#. assert_equal( +#. swap_keys_values({'apple': 'pomme', 'box': 'boite'}), +#. {'pomme': 'apple', 'boite': 'box'}, +#. ) +msgid "code_bits.swap_keys_values" +msgstr "swap_keys_values" + #. https://poeditor.com/projects/view_terms?id=490053&search=pages.BuildingUpStrings.steps.name_triangle.text #. #. temp = hello @@ -17975,6 +18660,25 @@ msgstr "surround" msgid "code_bits.temp" msgstr "temp" +#. https://poeditor.com/projects/view_terms?id=490053&search=pages.CreatingKeyValuePairs.steps.buy_quantity_exercise.text +#. +#. def buy_quantity(quantities): +#. print('Item:') +#. item = input() +#. print('Quantity:') +#. ... +#. +#. def test(): +#. quantities = {} +#. buy_quantity(quantities) +#. print(quantities) +#. buy_quantity(quantities) +#. print(quantities) +#. +#. test() +#. +#. ------ +#. #. https://poeditor.com/projects/view_terms?id=490053&search=pages.MakingTheBoard.steps.final_text.text #. #. def make_board(size): @@ -18434,6 +19138,26 @@ msgstr "total" msgid "code_bits.total_cost" msgstr "total_cost" +#. https://poeditor.com/projects/view_terms?id=490053&search=pages.CreatingKeyValuePairs.steps.total_cost_per_item_exercise +#. +#. def total_cost_per_item(quantities, prices): +#. totals = {} +#. for item in quantities: +#. totals[item] = quantities[item] * prices[item] +#. return totals +msgid "code_bits.total_cost_per_item" +msgstr "total_cost_per_item" + +#. https://poeditor.com/projects/view_terms?id=490053&search=pages.CreatingKeyValuePairs.steps.total_cost_per_item_exercise +#. +#. def total_cost_per_item(quantities, prices): +#. totals = {} +#. for item in quantities: +#. totals[item] = quantities[item] * prices[item] +#. return totals +msgid "code_bits.totals" +msgstr "totals" + #. https://poeditor.com/projects/view_terms?id=490053&search=pages.DictionaryKeysAndValues.steps.nested_dictionaries #. #. def print_words(words): @@ -18526,6 +19250,17 @@ msgstr "upper" msgid "code_bits.valid_image" msgstr "valid_image" +#. https://poeditor.com/projects/view_terms?id=490053&search=pages.CreatingKeyValuePairs.steps.swap_keys_values_exercise +#. +#. def swap_keys_values(d): +#. new_dict = {} +#. for key in d: +#. value = d[key] +#. new_dict[value] = key +#. return new_dict +#. +#. ------ +#. #. https://poeditor.com/projects/view_terms?id=490053&search=pages.FunctionsAndMethodsForLists.steps.index_predict_exercise.text #. #. some_list.index(value) @@ -21483,6 +22218,469 @@ msgstr "" msgid "pages.CombiningCompoundStatements.title" msgstr "Combining Compound Statements" +#. https://futurecoder.io/course/#CreatingKeyValuePairs +#. +#. https://poeditor.com/projects/view_terms?id=490053&search=pages.CreatingKeyValuePairs.steps.buy_quantity_exercise +msgid "pages.CreatingKeyValuePairs.steps.buy_quantity_exercise.hints.0.text" +msgstr "The function needs to get two inputs from the user: the item name and the quantity." + +#. https://futurecoder.io/course/#CreatingKeyValuePairs +#. +#. https://poeditor.com/projects/view_terms?id=490053&search=pages.CreatingKeyValuePairs.steps.buy_quantity_exercise +msgid "pages.CreatingKeyValuePairs.steps.buy_quantity_exercise.hints.1.text" +msgstr "The item name is already stored in the `item` variable. You need to get the quantity similarly." + +#. https://futurecoder.io/course/#CreatingKeyValuePairs +#. +#. https://poeditor.com/projects/view_terms?id=490053&search=pages.CreatingKeyValuePairs.steps.buy_quantity_exercise +msgid "pages.CreatingKeyValuePairs.steps.buy_quantity_exercise.hints.2.text" +msgstr "Remember that `input()` returns a string. The quantity needs to be stored as a number (`int`)." + +#. https://futurecoder.io/course/#CreatingKeyValuePairs +#. +#. https://poeditor.com/projects/view_terms?id=490053&search=pages.CreatingKeyValuePairs.steps.buy_quantity_exercise +msgid "pages.CreatingKeyValuePairs.steps.buy_quantity_exercise.hints.3.text" +msgstr "How do you convert a string to an integer?" + +#. https://futurecoder.io/course/#CreatingKeyValuePairs +#. +#. https://poeditor.com/projects/view_terms?id=490053&search=pages.CreatingKeyValuePairs.steps.buy_quantity_exercise +msgid "pages.CreatingKeyValuePairs.steps.buy_quantity_exercise.hints.4.text" +msgstr "" +"Once you have the `item` (string) and the quantity (integer), you need to add them to the `quantities` dictionary." + +#. https://futurecoder.io/course/#CreatingKeyValuePairs +#. +#. https://poeditor.com/projects/view_terms?id=490053&search=pages.CreatingKeyValuePairs.steps.buy_quantity_exercise +msgid "pages.CreatingKeyValuePairs.steps.buy_quantity_exercise.hints.5.text" +msgstr "Use the dictionary assignment syntax you just learned: `dictionary[key] = value`." + +#. https://futurecoder.io/course/#CreatingKeyValuePairs +#. +#. https://poeditor.com/projects/view_terms?id=490053&search=pages.CreatingKeyValuePairs.steps.buy_quantity_exercise +msgid "pages.CreatingKeyValuePairs.steps.buy_quantity_exercise.hints.6.text" +msgstr "What should be the key and what should be the value in this case?" + +#. https://futurecoder.io/course/#CreatingKeyValuePairs +msgid "pages.CreatingKeyValuePairs.steps.buy_quantity_exercise.requirements" +msgstr "Your function should modify the `quantities` argument. It doesn't need to `return` or `print` anything." + +#. https://futurecoder.io/course/#CreatingKeyValuePairs +#. +#. # __code0__: +#. def buy_quantity(quantities): +#. print('Item:') +#. item = input() +#. print('Quantity:') +#. ... +#. +#. def test(): +#. quantities = {} +#. buy_quantity(quantities) +#. print(quantities) +#. buy_quantity(quantities) +#. print(quantities) +#. +#. test() +#. +#. https://poeditor.com/projects/view_terms?id=490053&search=code_bits.%27Item%3A%27 +#. +#. https://poeditor.com/projects/view_terms?id=490053&search=code_bits.%27Quantity%3A%27 +#. +#. https://poeditor.com/projects/view_terms?id=490053&search=code_bits.buy_quantity +#. +#. https://poeditor.com/projects/view_terms?id=490053&search=code_bits.item +#. +#. https://poeditor.com/projects/view_terms?id=490053&search=code_bits.quantities +#. +#. https://poeditor.com/projects/view_terms?id=490053&search=code_bits.test +msgid "pages.CreatingKeyValuePairs.steps.buy_quantity_exercise.text" +msgstr "" +"That's exactly what we need. When the customer says they want 5 million boxes,\n" +"we can just put that information directly into our dictionary. So as an exercise, let's make a generic version of that.\n" +"Write a function `buy_quantity(quantities)` which calls `input()` twice to get an item name and quantity from the user\n" +"and assigns them in the `quantities` dictionary. Here's some starting code:\n" +"\n" +" __copyable__\n" +"__code0__\n" +"\n" +"and an example of how a session should look:\n" +"\n" +" Item:\n" +" dog\n" +" Quantity:\n" +" 5000000\n" +" {'dog': 5000000}\n" +" Item:\n" +" box\n" +" Quantity:\n" +" 2\n" +" {'dog': 5000000, 'box': 2}\n" +"\n" +"Note that `buy_quantity` should *modify* the dictionary that's passed in, and doesn't need to return anything.\n" +"You can assume that the user will enter a valid integer for the quantity." + +#. https://poeditor.com/projects/view_terms?id=490053&search=pages.CreatingKeyValuePairs.steps.dict_assignment_valid +msgid "pages.CreatingKeyValuePairs.steps.dict_assignment_valid.output_prediction_choices.1" +msgstr "{'dog': 5000000}" + +#. https://poeditor.com/projects/view_terms?id=490053&search=pages.CreatingKeyValuePairs.steps.dict_assignment_valid +msgid "pages.CreatingKeyValuePairs.steps.dict_assignment_valid.output_prediction_choices.2" +msgstr "{'box': 2}" + +#. https://poeditor.com/projects/view_terms?id=490053&search=pages.CreatingKeyValuePairs.steps.dict_assignment_valid +msgid "pages.CreatingKeyValuePairs.steps.dict_assignment_valid.output_prediction_choices.3" +msgstr "{'dog': 5000000, 'box': 2}" + +#. https://poeditor.com/projects/view_terms?id=490053&search=pages.CreatingKeyValuePairs.steps.dict_assignment_valid +msgid "pages.CreatingKeyValuePairs.steps.dict_assignment_valid.output_prediction_choices.4" +msgstr "{'box': 2, 'dog': 5000000}" + +#. https://futurecoder.io/course/#CreatingKeyValuePairs +#. +#. # __code0__: +#. __program_indented__ +#. +#. https://poeditor.com/projects/view_terms?id=490053&search=code_bits.__program_indented__ +msgid "pages.CreatingKeyValuePairs.steps.dict_assignment_valid.text" +msgstr "" +"Sorry, that's not allowed. For lists, subscript assignment only works for existing valid indices.\n" +"But that's not true for dictionaries! Try this:\n" +"\n" +" __copyable__\n" +"__code0__\n" +"\n" +"Note that `{}` means an empty dictionary, i.e. a dictionary with no key-value pairs.\n" +"This is similar to `[]` meaning an empty list or `\"\"` meaning an empty string." + +#. https://futurecoder.io/course/#CreatingKeyValuePairs +#. +#. # __code0__: +#. reverse = swap_keys_values(letters) +#. +#. https://poeditor.com/projects/view_terms?id=490053&search=code_bits.letters +#. +#. https://poeditor.com/projects/view_terms?id=490053&search=code_bits.reverse +#. +#. https://poeditor.com/projects/view_terms?id=490053&search=code_bits.swap_keys_values +msgid "pages.CreatingKeyValuePairs.steps.final_text.text" +msgstr "" +"Magnificent!\n" +"\n" +"Jokes aside, it's important to remember how exactly this can go wrong. Just like multiple items in the store\n" +"can have the same price, multiple words in English can have the same translation in French. If the original dictionary\n" +"has duplicate *values*, what happens when you try to swap keys and values? Since dictionary keys must be unique,\n" +"some data will be lost.\n" +"\n" +"But there are many situations where you can be sure that the values in a dictionary *are* unique and that this\n" +"'inversion' makes sense. For example, we saw this code [earlier in the chapter](#UsingDictionariesInPractice):\n" +"\n" +" __copyable__\n" +" __no_auto_translate__\n" +" def substitute(string, d):\n" +" result = \"\"\n" +" for letter in string:\n" +" result += d[letter]\n" +" return result\n" +"\n" +" plaintext = 'helloworld'\n" +" encrypted = 'qpeefifmez'\n" +" letters = {'h': 'q', 'e': 'p', 'l': 'e', 'o': 'f', 'w': 'i', 'r': 'm', 'd': 'z'}\n" +" reverse = {'q': 'h', 'p': 'e', 'e': 'l', 'f': 'o', 'i': 'w', 'm': 'r', 'z': 'd'}\n" +" assert_equal(substitute(plaintext, letters), encrypted)\n" +" assert_equal(substitute(encrypted, reverse), plaintext)\n" +"\n" +"Now we can construct the `reverse` dictionary automatically:\n" +"\n" +"__code0__\n" +"\n" +"For this to work, we just have to make sure that all the values in `letters` are unique.\n" +"Otherwise it would be impossible to decrypt messages properly. If both `'h'` and `'j'` got replaced with `'q'`\n" +"during encryption, there would be no way to know whether `'qpeef'` means `'hello'` or `'jello'`!" + +#. https://futurecoder.io/course/#CreatingKeyValuePairs +#. +#. # __code0__: +#. __program_indented__ +#. +#. https://poeditor.com/projects/view_terms?id=490053&search=code_bits.__program_indented__ +msgid "pages.CreatingKeyValuePairs.steps.list_append_reminder.text" +msgstr "" +"Now we'll learn how to add key-value pairs to a dictionary,\n" +"e.g. so that we can keep track of what the customer is buying.\n" +"Before looking at dictionaries, let's remind ourselves how to add items to a list. Run this program:\n" +"\n" +" __copyable__\n" +"__code0__" + +#. https://futurecoder.io/course/#CreatingKeyValuePairs +#. +#. # __code0__: +#. __program_indented__ +#. +#. https://poeditor.com/projects/view_terms?id=490053&search=code_bits.__program_indented__ +msgid "pages.CreatingKeyValuePairs.steps.list_assign_invalid.text" +msgstr "" +"What if we used that idea to create our list in the first place?\n" +"We know we want a list where `cart[0]` is `'dog'` and `cart[1]` is `'box'`, so let's just say that:\n" +"\n" +" __copyable__\n" +"__code0__" + +#. https://poeditor.com/projects/view_terms?id=490053&search=pages.CreatingKeyValuePairs.steps.list_assign_reminder +msgid "pages.CreatingKeyValuePairs.steps.list_assign_reminder.output_prediction_choices.0" +msgstr "['dog', 'box']" + +#. https://poeditor.com/projects/view_terms?id=490053&search=pages.CreatingKeyValuePairs.steps.list_assign_reminder +msgid "pages.CreatingKeyValuePairs.steps.list_assign_reminder.output_prediction_choices.1" +msgstr "['box', 'cat']" + +#. https://poeditor.com/projects/view_terms?id=490053&search=pages.CreatingKeyValuePairs.steps.list_assign_reminder +msgid "pages.CreatingKeyValuePairs.steps.list_assign_reminder.output_prediction_choices.2" +msgstr "['dog', 'cat']" + +#. https://futurecoder.io/course/#CreatingKeyValuePairs +#. +#. # __code0__: +#. __program_indented__ +#. +#. https://poeditor.com/projects/view_terms?id=490053&search=code_bits.__program_indented__ +msgid "pages.CreatingKeyValuePairs.steps.list_assign_reminder.text" +msgstr "" +"Pretty simple. We can also change the value at an index, replacing it with a different one:\n" +"\n" +" __copyable__\n" +"__code0__" + +#. https://futurecoder.io/course/#CreatingKeyValuePairs +#. +#. https://poeditor.com/projects/view_terms?id=490053&search=pages.CreatingKeyValuePairs.steps.make_english_to_german_exercise +msgid "pages.CreatingKeyValuePairs.steps.make_english_to_german_exercise.hints.0.text" +msgstr "You need to create a new empty dictionary, let's call it `english_to_german`." + +#. https://futurecoder.io/course/#CreatingKeyValuePairs +#. +#. https://poeditor.com/projects/view_terms?id=490053&search=pages.CreatingKeyValuePairs.steps.make_english_to_german_exercise +msgid "pages.CreatingKeyValuePairs.steps.make_english_to_german_exercise.hints.1.text" +msgstr "Iterate through the keys (English words) of the `english_to_french` dictionary." + +#. https://futurecoder.io/course/#CreatingKeyValuePairs +#. +#. https://poeditor.com/projects/view_terms?id=490053&search=pages.CreatingKeyValuePairs.steps.make_english_to_german_exercise +msgid "pages.CreatingKeyValuePairs.steps.make_english_to_german_exercise.hints.2.text" +msgstr "Inside the loop, for each `english` word:" + +#. https://futurecoder.io/course/#CreatingKeyValuePairs +#. +#. https://poeditor.com/projects/view_terms?id=490053&search=pages.CreatingKeyValuePairs.steps.make_english_to_german_exercise +msgid "pages.CreatingKeyValuePairs.steps.make_english_to_german_exercise.hints.3.text" +msgstr "1. Find the corresponding French word using `english_to_french`." + +#. https://futurecoder.io/course/#CreatingKeyValuePairs +#. +#. https://poeditor.com/projects/view_terms?id=490053&search=pages.CreatingKeyValuePairs.steps.make_english_to_german_exercise +msgid "pages.CreatingKeyValuePairs.steps.make_english_to_german_exercise.hints.4.text" +msgstr "2. Use that French word as a key to find the German word in `french_to_german`." + +#. https://futurecoder.io/course/#CreatingKeyValuePairs +#. +#. https://poeditor.com/projects/view_terms?id=490053&search=pages.CreatingKeyValuePairs.steps.make_english_to_german_exercise +msgid "pages.CreatingKeyValuePairs.steps.make_english_to_german_exercise.hints.5.text" +msgstr "" +"3. Add the `english` word as a key and the `german` word as the value to your new `english_to_german` dictionary." + +#. https://futurecoder.io/course/#CreatingKeyValuePairs +#. +#. https://poeditor.com/projects/view_terms?id=490053&search=pages.CreatingKeyValuePairs.steps.make_english_to_german_exercise +msgid "pages.CreatingKeyValuePairs.steps.make_english_to_german_exercise.hints.6.text" +msgstr "After the loop, return the `english_to_german` dictionary." + +#. https://futurecoder.io/course/#CreatingKeyValuePairs +#. +#. # __code0__: +#. def make_english_to_german(english_to_french, french_to_german): +#. ... +#. +#. assert_equal( +#. make_english_to_german( +#. {'apple': 'pomme', 'box': 'boite'}, +#. {'pomme': 'apfel', 'boite': 'kasten'}, +#. ), +#. {'apple': 'apfel', 'box': 'kasten'}, +#. ) +#. +#. https://poeditor.com/projects/view_terms?id=490053&search=code_bits.%27apfel%27 +#. +#. https://poeditor.com/projects/view_terms?id=490053&search=code_bits.%27apple%27 +#. +#. https://poeditor.com/projects/view_terms?id=490053&search=code_bits.%27boite%27 +#. +#. https://poeditor.com/projects/view_terms?id=490053&search=code_bits.%27box%27 +#. +#. https://poeditor.com/projects/view_terms?id=490053&search=code_bits.%27kasten%27 +#. +#. https://poeditor.com/projects/view_terms?id=490053&search=code_bits.%27pomme%27 +#. +#. https://poeditor.com/projects/view_terms?id=490053&search=code_bits.assert_equal +#. +#. https://poeditor.com/projects/view_terms?id=490053&search=code_bits.english_to_french +#. +#. https://poeditor.com/projects/view_terms?id=490053&search=code_bits.french_to_german +#. +#. https://poeditor.com/projects/view_terms?id=490053&search=code_bits.make_english_to_german +msgid "pages.CreatingKeyValuePairs.steps.make_english_to_german_exercise.text" +msgstr "" +"Perfect! This is like having a nice receipt full of useful information.\n" +"\n" +"Let's come back to the example of using dictionaries for translation. Suppose we have one dictionary\n" +"for translating from English to French, and another for translating from French to German.\n" +"Let's use that to create a dictionary that translates from English to German:\n" +"\n" +" __copyable__\n" +"__code0__" + +#. https://futurecoder.io/course/#CreatingKeyValuePairs +#. +#. https://poeditor.com/projects/view_terms?id=490053&search=pages.CreatingKeyValuePairs.steps.swap_keys_values_exercise +msgid "pages.CreatingKeyValuePairs.steps.swap_keys_values_exercise.hints.0.text" +msgstr "Create a new empty dictionary to store the result." + +#. https://futurecoder.io/course/#CreatingKeyValuePairs +#. +#. https://poeditor.com/projects/view_terms?id=490053&search=pages.CreatingKeyValuePairs.steps.swap_keys_values_exercise +msgid "pages.CreatingKeyValuePairs.steps.swap_keys_values_exercise.hints.1.text" +msgstr "Iterate through the keys of the input dictionary `d`." + +#. https://futurecoder.io/course/#CreatingKeyValuePairs +#. +#. https://poeditor.com/projects/view_terms?id=490053&search=pages.CreatingKeyValuePairs.steps.swap_keys_values_exercise +msgid "pages.CreatingKeyValuePairs.steps.swap_keys_values_exercise.hints.2.text" +msgstr "Inside the loop, for each `key`:" + +#. https://futurecoder.io/course/#CreatingKeyValuePairs +#. +#. https://poeditor.com/projects/view_terms?id=490053&search=pages.CreatingKeyValuePairs.steps.swap_keys_values_exercise +msgid "pages.CreatingKeyValuePairs.steps.swap_keys_values_exercise.hints.3.text" +msgstr "1. Get the corresponding `value` from `d`." + +#. https://futurecoder.io/course/#CreatingKeyValuePairs +#. +#. https://poeditor.com/projects/view_terms?id=490053&search=pages.CreatingKeyValuePairs.steps.swap_keys_values_exercise +msgid "pages.CreatingKeyValuePairs.steps.swap_keys_values_exercise.hints.4.text" +msgstr "" +"2. Add an entry to the new dictionary where the *key* is the original `value` and the *value* is the original `key`." + +#. https://futurecoder.io/course/#CreatingKeyValuePairs +#. +#. https://poeditor.com/projects/view_terms?id=490053&search=pages.CreatingKeyValuePairs.steps.swap_keys_values_exercise +msgid "pages.CreatingKeyValuePairs.steps.swap_keys_values_exercise.hints.5.text" +msgstr "Return the new dictionary after the loop." + +#. https://futurecoder.io/course/#CreatingKeyValuePairs +#. +#. # __code0__: +#. def swap_keys_values(d): +#. ... +#. +#. assert_equal( +#. swap_keys_values({'apple': 'pomme', 'box': 'boite'}), +#. {'pomme': 'apple', 'boite': 'box'}, +#. ) +#. +#. https://poeditor.com/projects/view_terms?id=490053&search=code_bits.%27apple%27 +#. +#. https://poeditor.com/projects/view_terms?id=490053&search=code_bits.%27boite%27 +#. +#. https://poeditor.com/projects/view_terms?id=490053&search=code_bits.%27box%27 +#. +#. https://poeditor.com/projects/view_terms?id=490053&search=code_bits.%27pomme%27 +#. +#. https://poeditor.com/projects/view_terms?id=490053&search=code_bits.assert_equal +#. +#. https://poeditor.com/projects/view_terms?id=490053&search=code_bits.swap_keys_values +msgid "pages.CreatingKeyValuePairs.steps.swap_keys_values_exercise.text" +msgstr "" +"Great job!\n" +"\n" +"Of course, language isn't so simple, and there are many ways that using a dictionary like this could go wrong.\n" +"So...let's do something even worse! Write a function which takes a dictionary and swaps the keys and values,\n" +"so `a: b` becomes `b: a`.\n" +"\n" +" __copyable__\n" +"__code0__" + +#. https://futurecoder.io/course/#CreatingKeyValuePairs +#. +#. https://poeditor.com/projects/view_terms?id=490053&search=pages.CreatingKeyValuePairs.steps.total_cost_per_item_exercise +msgid "pages.CreatingKeyValuePairs.steps.total_cost_per_item_exercise.hints.0.text" +msgstr "You need to iterate through the items in the `quantities` dictionary." + +#. https://futurecoder.io/course/#CreatingKeyValuePairs +#. +#. https://poeditor.com/projects/view_terms?id=490053&search=pages.CreatingKeyValuePairs.steps.total_cost_per_item_exercise +msgid "pages.CreatingKeyValuePairs.steps.total_cost_per_item_exercise.hints.1.text" +msgstr "For each `item`, calculate the total cost for that item (quantity * price)." + +#. https://futurecoder.io/course/#CreatingKeyValuePairs +#. +#. https://poeditor.com/projects/view_terms?id=490053&search=pages.CreatingKeyValuePairs.steps.total_cost_per_item_exercise +msgid "pages.CreatingKeyValuePairs.steps.total_cost_per_item_exercise.hints.2.text" +msgstr "Store this calculated cost in the `totals` dictionary." + +#. https://futurecoder.io/course/#CreatingKeyValuePairs +#. +#. https://poeditor.com/projects/view_terms?id=490053&search=pages.CreatingKeyValuePairs.steps.total_cost_per_item_exercise +msgid "pages.CreatingKeyValuePairs.steps.total_cost_per_item_exercise.hints.3.text" +msgstr "The key for the `totals` dictionary should be the `item` name." + +#. https://futurecoder.io/course/#CreatingKeyValuePairs +#. +#. https://poeditor.com/projects/view_terms?id=490053&search=pages.CreatingKeyValuePairs.steps.total_cost_per_item_exercise +msgid "pages.CreatingKeyValuePairs.steps.total_cost_per_item_exercise.hints.4.text" +msgstr "Use the dictionary assignment syntax: `totals[item] = calculated_cost`." + +#. https://futurecoder.io/course/#CreatingKeyValuePairs +#. +#. https://poeditor.com/projects/view_terms?id=490053&search=pages.CreatingKeyValuePairs.steps.total_cost_per_item_exercise +msgid "pages.CreatingKeyValuePairs.steps.total_cost_per_item_exercise.hints.5.text" +msgstr "Make sure this assignment happens *inside* the loop." + +#. https://futurecoder.io/course/#CreatingKeyValuePairs +#. +#. https://poeditor.com/projects/view_terms?id=490053&search=pages.CreatingKeyValuePairs.steps.total_cost_per_item_exercise +msgid "pages.CreatingKeyValuePairs.steps.total_cost_per_item_exercise.hints.6.text" +msgstr "The function should return the `totals` dictionary after the loop finishes." + +#. https://futurecoder.io/course/#CreatingKeyValuePairs +msgid "pages.CreatingKeyValuePairs.steps.total_cost_per_item_exercise.text" +msgstr "" +"Well done!\n" +"\n" +"Next exercise: earlier we defined a function `total_cost(quantities, prices)` which returned a single number\n" +"with a grand total of all the items in the cart. Now let's make a function `total_cost_per_item(quantities, prices)`\n" +"which returns a new dictionary with the total cost for each item:\n" +"\n" +" __copyable__\n" +" def total_cost_per_item(quantities, prices):\n" +" totals = {}\n" +" for item in quantities:\n" +" ... = quantities[item] * prices[item]\n" +" return totals\n" +"\n" +" assert_equal(\n" +" total_cost_per_item({'apple': 2}, {'apple': 3, 'box': 5}),\n" +" {'apple': 6},\n" +" )\n" +"\n" +" assert_equal(\n" +" total_cost_per_item({'dog': 5000000, 'box': 2}, {'dog': 100, 'box': 5}),\n" +" {'dog': 500000000, 'box': 10},\n" +" )" + +#. https://futurecoder.io/course/#CreatingKeyValuePairs +msgid "pages.CreatingKeyValuePairs.title" +msgstr "Creating Key-Value Pairs" + #. https://futurecoder.io/course/#DefiningFunctions #. #. https://poeditor.com/projects/view_terms?id=490053&search=pages.DefiningFunctions.steps.change_function_name diff --git a/translations/locales/en/LC_MESSAGES/futurecoder.mo b/translations/locales/en/LC_MESSAGES/futurecoder.mo index 03910361628a1a71198bc484fa5bf0eba822d73f..5b843e1d940c895c6dfe605d16bf2ddc52d054e0 100644 GIT binary patch delta 35123 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 Jjy>7_{{Uok_O<{3 From 391edca048ef0751471ad29a00d5cfc907d0145a Mon Sep 17 00:00:00 2001 From: Alex Hall Date: Sun, 30 Mar 2025 16:34:38 +0200 Subject: [PATCH 2/3] tweaks --- core/chapters/c12_dictionaries.py | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/core/chapters/c12_dictionaries.py b/core/chapters/c12_dictionaries.py index 7cba16e2..facc56e7 100644 --- a/core/chapters/c12_dictionaries.py +++ b/core/chapters/c12_dictionaries.py @@ -784,9 +784,10 @@ def test(): Note that `buy_quantity` should *modify* the dictionary that's passed in, and doesn't need to return anything. You can assume that the user will enter a valid integer for the quantity. + You can also assume that the user won't enter an item that's already in `quantities`. """ requirements = "Your function should modify the `quantities` argument. It doesn't need to `return` or `print` anything." - no_returns_stdout = True # The function itself doesn't print/return, the test harness does + no_returns_stdout = True hints = """ The function needs to get two inputs from the user: the item name and the quantity. @@ -1022,7 +1023,7 @@ def swap_keys_values(d: Dict[str, str]): some data will be lost. But there are many situations where you can be sure that the values in a dictionary *are* unique and that this -'inversion' makes sense. For example, we saw this code [earlier in the chapter](#UsingDictionariesInPractice): +'inversion' makes sense. For example, we saw this code [earlier in the chapter](#UsingDictionaries): __copyable__ __no_auto_translate__ From 73421388171842891ef078ea6e15acaab3664ae5 Mon Sep 17 00:00:00 2001 From: Alex Hall Date: Sun, 6 Apr 2025 09:32:55 +0200 Subject: [PATCH 3/3] CopyingDictionaries --- core/chapters/c12_dictionaries.py | 241 +++++ tests/golden_files/en/test_transcript.json | 105 ++ translations/english.po | 998 +++++++++++++++++- .../locales/en/LC_MESSAGES/futurecoder.mo | Bin 308487 -> 315576 bytes 4 files changed, 1342 insertions(+), 2 deletions(-) diff --git a/core/chapters/c12_dictionaries.py b/core/chapters/c12_dictionaries.py index facc56e7..0249df55 100644 --- a/core/chapters/c12_dictionaries.py +++ b/core/chapters/c12_dictionaries.py @@ -1048,3 +1048,244 @@ def substitute(string, d): Otherwise it would be impossible to decrypt messages properly. If both `'h'` and `'j'` got replaced with `'q'` during encryption, there would be no way to know whether `'qpeef'` means `'hello'` or `'jello'`! """ + + +class CopyingDictionaries(Page): + title = "Copying Dictionaries" + + class shared_references(VerbatimStep): + """ + Remember how assigning one list variable to another (`list2 = list1`) made both names point to the *same* list? Dictionaries work the same way because they are also *mutable* (can be changed). + + Predict what the following code will print, then run it to see: + + __copyable__ + __program_indented__ + """ + def program(self): + d1 = {'a': 1, 'b': 2} + d2 = d1 + + print("d1 before:", d1) + print("d2 before:", d2) + print("Are they the same object?", d1 is d2) + + d2['c'] = 3 # Modify via d2 + + print("d1 after:", d1) # Is d1 affected? + print("d2 after:", d2) + + predicted_output_choices = [ + # Incorrect prediction (d1 unaffected) + """d1 before: {'a': 1, 'b': 2} +d2 before: {'a': 1, 'b': 2} +Are they the same object? True +d1 after: {'a': 1, 'b': 2} +d2 after: {'a': 1, 'b': 2, 'c': 3}""", + + # Correct prediction + """d1 before: {'a': 1, 'b': 2} +d2 before: {'a': 1, 'b': 2} +Are they the same object? True +d1 after: {'a': 1, 'b': 2, 'c': 3} +d2 after: {'a': 1, 'b': 2, 'c': 3}""", + + # Incorrect prediction (is False) + """d1 before: {'a': 1, 'b': 2} +d2 before: {'a': 1, 'b': 2} +Are they the same object? False +d1 after: {'a': 1, 'b': 2} +d2 after: {'a': 1, 'b': 2, 'c': 3}""", + ] + + class making_copies(VerbatimStep): + """ + Because `d1` and `d2` referred to the exact same dictionary object (`d1 is d2` was `True`), changing it via `d2` also changed what `d1` saw. + + To get a *separate* dictionary with the same contents, use the `.copy()` method. + + Predict how using `.copy()` changes the outcome, then run this code: + + __copyable__ + __program_indented__ + """ + def program(self): + d1 = {'a': 1, 'b': 2} + d2 = d1.copy() # Create a separate copy + + print("d1 before:", d1) + print("d2 before:", d2) + print("Are they the same object?", d1 is d2) + + d2['c'] = 3 # Modify the copy + + print("d1 after:", d1) # Is d1 affected now? + print("d2 after:", d2) + + predicted_output_choices = [ + # Incorrect prediction (is True) + """d1 before: {'a': 1, 'b': 2} +d2 before: {'a': 1, 'b': 2} +Are they the same object? True +d1 after: {'a': 1, 'b': 2, 'c': 3} +d2 after: {'a': 1, 'b': 2, 'c': 3}""", + + # Incorrect prediction (d1 affected) + """d1 before: {'a': 1, 'b': 2} +d2 before: {'a': 1, 'b': 2} +Are they the same object? False +d1 after: {'a': 1, 'b': 2, 'c': 3} +d2 after: {'a': 1, 'b': 2, 'c': 3}""", + + # Correct prediction + """d1 before: {'a': 1, 'b': 2} +d2 before: {'a': 1, 'b': 2} +Are they the same object? False +d1 after: {'a': 1, 'b': 2} +d2 after: {'a': 1, 'b': 2, 'c': 3}""", + ] + + class positive_stock_exercise(ExerciseStep): + """ + Making an exact copy is useful, but often we want a *modified* copy. Let's practice creating a new dictionary based on an old one. + + Write a function `positive_stock(stock)` that takes a dictionary `stock` (mapping item names to integer quantities) and returns a *new* dictionary containing only the items from the original `stock` where the quantity is strictly greater than 0. The original `stock` dictionary should not be changed. + + __copyable__ + def positive_stock(stock): + # Your code here + ... + + assert_equal( + positive_stock({'apple': 10, 'banana': 0, 'pear': 5, 'orange': 0}), + {'apple': 10, 'pear': 5} + ) + assert_equal( + positive_stock({'pen': 0, 'pencil': 0}), + {} + ) + assert_equal( + positive_stock({'book': 1, 'paper': 5}), + {'book': 1, 'paper': 5} + ) + """ + hints = """ + Start by creating a new empty dictionary, e.g., `result = {}`. + Loop through the keys of the input `stock` dictionary. + Inside the loop, get the `quantity` for the current `item` using `stock[item]`. + Use an `if` statement to check if `quantity > 0`. + If the quantity is positive, add the `item` and its `quantity` to your `result` dictionary using `result[item] = quantity`. + After the loop finishes, return the `result` dictionary. + Make sure you don't modify the original `stock` dictionary passed into the function. Creating a new `result` dictionary ensures this. + """ + + def solution(self): + def positive_stock(stock: Dict[str, int]): + result = {} + for item in stock: + quantity = stock[item] + if quantity > 0: + result[item] = quantity + return result + return positive_stock + + tests = [ + (({'apple': 10, 'banana': 0, 'pear': 5, 'orange': 0},), {'apple': 10, 'pear': 5}), + (({'pen': 0, 'pencil': 0},), {}), + (({'book': 1, 'paper': 5},), {'book': 1, 'paper': 5}), + (({},), {}), # Empty input + (({'gadget': -5, 'widget': 3},), {'widget': 3}), # Negative values + ] + + @classmethod + def generate_inputs(cls): + # Generate a dictionary with some zero/negative and positive values + stock = {} + num_items = random.randint(3, 8) + for _ in range(num_items): + item = generate_string(random.randint(3, 6)) + # Ensure some variety in quantities + if random.random() < 0.4: + quantity = 0 + elif random.random() < 0.2: + quantity = random.randint(-5, -1) + else: + quantity = random.randint(1, 20) + stock[item] = quantity + # Ensure at least one positive if dict not empty + if stock and all(q <= 0 for q in stock.values()): + stock[generate_string(4)] = random.randint(1, 10) + return {"stock": stock} + + class add_item_exercise(ExerciseStep): + """ + Let's practice combining copying and modifying. Imagine we want to represent adding one unit of an item to our stock count. + + Write a function `add_item(item, quantities)` that takes an item name (`item`) and a dictionary `quantities`. You can assume the `item` *already exists* as a key in the `quantities` dictionary. + + The function should return a *new* dictionary which is a copy of `quantities`, but with the value associated with `item` increased by 1. The original `quantities` dictionary should not be changed. + + __copyable__ + def add_item(item, quantities): + # Your code here + ... + + stock = {'apple': 5, 'banana': 2} + new_stock = add_item('apple', stock) + assert_equal(stock, {'apple': 5, 'banana': 2}) # Original unchanged + assert_equal(new_stock, {'apple': 6, 'banana': 2}) # Copy has incremented value + + new_stock_2 = add_item('banana', new_stock) + assert_equal(new_stock, {'apple': 6, 'banana': 2}) # Previous copy unchanged + assert_equal(new_stock_2, {'apple': 6, 'banana': 3}) # New copy incremented + """ + hints = """ + First, create a *copy* of the input `quantities` dictionary using the `.copy()` method. Store this in a new variable, e.g., `new_quantities`. + Since we assume `item` is already a key, you don't need to check for its existence in this exercise. + Find the current quantity of the `item` in the `new_quantities` copy using `new_quantities[item]`. + Calculate the new quantity by adding 1 to the current quantity. + Update the value for `item` in the `new_quantities` copy with this new quantity using assignment: `new_quantities[item] = ...`. + Return the `new_quantities` dictionary. + """ + + def solution(self): + def add_item(item: str, quantities: Dict[str, int]): + new_quantities = quantities.copy() + new_quantities[item] = new_quantities[item] + 1 + return new_quantities + return add_item + + tests = [ + (('apple', {'apple': 5, 'banana': 2}), {'apple': 6, 'banana': 2}), + (('banana', {'apple': 6, 'banana': 2}), {'apple': 6, 'banana': 3}), + (('pen', {'pen': 1}), {'pen': 2}), + (('a', {'a': 0, 'b': 99}), {'a': 1, 'b': 99}), + ] + + @classmethod + def generate_inputs(cls): + quantities = generate_dict(str, int) + # Ensure the dictionary is not empty + if not quantities: + quantities[generate_string(4)] = random.randint(0, 10) + # Pick an existing item to increment + item = random.choice(list(quantities.keys())) + return {"item": item, "quantities": quantities} + + final_text = """ + Well done! Notice that the line where you increment the value: + + new_quantities[item] = new_quantities[item] + 1 + + can also be written more concisely using the `+=` operator, just like with numbers: + + new_quantities[item] += 1 + + This does the same thing: it reads the current value, adds 1, and assigns the result back. + """ + + final_text = """ + Great! You now know why copying dictionaries is important (because they are mutable) and how to do it using `.copy()`. You've also practiced creating modified copies, which is a common and safe way to work with data without accidentally changing things elsewhere in your program. + + Next, we'll see how to check if a key exists *before* trying to use it, to avoid errors. + """ \ No newline at end of file diff --git a/tests/golden_files/en/test_transcript.json b/tests/golden_files/en/test_transcript.json index 47ed4659..99b77e70 100644 --- a/tests/golden_files/en/test_transcript.json +++ b/tests/golden_files/en/test_transcript.json @@ -7437,5 +7437,110 @@ "result": [] }, "step": "swap_keys_values_exercise" + }, + { + "get_solution": "program", + "page": "Copying Dictionaries", + "program": [ + "d1 = {'a': 1, 'b': 2}", + "d2 = d1", + "", + "print(\"d1 before:\", d1)", + "print(\"d2 before:\", d2)", + "print(\"Are they the same object?\", d1 is d2)", + "", + "d2['c'] = 3 # Modify via d2", + "", + "print(\"d1 after:\", d1) # Is d1 affected?", + "print(\"d2 after:\", d2)" + ], + "response": { + "passed": true, + "prediction": { + "answer": "d1 before: {'a': 1, 'b': 2}\nd2 before: {'a': 1, 'b': 2}\nAre they the same object? True\nd1 after: {'a': 1, 'b': 2, 'c': 3}\nd2 after: {'a': 1, 'b': 2, 'c': 3}", + "choices": [ + "d1 before: {'a': 1, 'b': 2}\nd2 before: {'a': 1, 'b': 2}\nAre they the same object? True\nd1 after: {'a': 1, 'b': 2}\nd2 after: {'a': 1, 'b': 2, 'c': 3}", + "d1 before: {'a': 1, 'b': 2}\nd2 before: {'a': 1, 'b': 2}\nAre they the same object? True\nd1 after: {'a': 1, 'b': 2, 'c': 3}\nd2 after: {'a': 1, 'b': 2, 'c': 3}", + "d1 before: {'a': 1, 'b': 2}\nd2 before: {'a': 1, 'b': 2}\nAre they the same object? False\nd1 after: {'a': 1, 'b': 2}\nd2 after: {'a': 1, 'b': 2, 'c': 3}", + "Error" + ] + }, + "result": [ + { + "text": "d1 before: {'a': 1, 'b': 2}\nd2 before: {'a': 1, 'b': 2}\nAre they the same object? True\nd1 after: {'a': 1, 'b': 2, 'c': 3}\nd2 after: {'a': 1, 'b': 2, 'c': 3}\n", + "type": "stdout" + } + ] + }, + "step": "shared_references" + }, + { + "get_solution": "program", + "page": "Copying Dictionaries", + "program": [ + "d1 = {'a': 1, 'b': 2}", + "d2 = d1.copy() # Create a separate copy", + "", + "print(\"d1 before:\", d1)", + "print(\"d2 before:\", d2)", + "print(\"Are they the same object?\", d1 is d2)", + "", + "d2['c'] = 3 # Modify the copy", + "", + "print(\"d1 after:\", d1) # Is d1 affected now?", + "print(\"d2 after:\", d2)" + ], + "response": { + "passed": true, + "prediction": { + "answer": "d1 before: {'a': 1, 'b': 2}\nd2 before: {'a': 1, 'b': 2}\nAre they the same object? False\nd1 after: {'a': 1, 'b': 2}\nd2 after: {'a': 1, 'b': 2, 'c': 3}", + "choices": [ + "d1 before: {'a': 1, 'b': 2}\nd2 before: {'a': 1, 'b': 2}\nAre they the same object? True\nd1 after: {'a': 1, 'b': 2, 'c': 3}\nd2 after: {'a': 1, 'b': 2, 'c': 3}", + "d1 before: {'a': 1, 'b': 2}\nd2 before: {'a': 1, 'b': 2}\nAre they the same object? False\nd1 after: {'a': 1, 'b': 2, 'c': 3}\nd2 after: {'a': 1, 'b': 2, 'c': 3}", + "d1 before: {'a': 1, 'b': 2}\nd2 before: {'a': 1, 'b': 2}\nAre they the same object? False\nd1 after: {'a': 1, 'b': 2}\nd2 after: {'a': 1, 'b': 2, 'c': 3}", + "Error" + ] + }, + "result": [ + { + "text": "d1 before: {'a': 1, 'b': 2}\nd2 before: {'a': 1, 'b': 2}\nAre they the same object? False\nd1 after: {'a': 1, 'b': 2}\nd2 after: {'a': 1, 'b': 2, 'c': 3}\n", + "type": "stdout" + } + ] + }, + "step": "making_copies" + }, + { + "get_solution": "program", + "page": "Copying Dictionaries", + "program": [ + "def positive_stock(stock):", + " result = {}", + " for item in stock:", + " quantity = stock[item]", + " if quantity > 0:", + " result[item] = quantity", + " return result" + ], + "response": { + "passed": true, + "result": [] + }, + "step": "positive_stock_exercise" + }, + { + "get_solution": "program", + "page": "Copying Dictionaries", + "program": [ + "def add_item(item, quantities):", + " new_quantities = quantities.copy()", + " new_quantities[item] = new_quantities[item] + 1", + " return new_quantities" + ], + "response": { + "passed": true, + "result": [] + }, + "step": "add_item_exercise" } ] \ No newline at end of file diff --git a/translations/english.po b/translations/english.po index ca2e6007..979f5305 100644 --- a/translations/english.po +++ b/translations/english.po @@ -536,6 +536,38 @@ msgstr "\"Alice's Diner\"" msgid "code_bits.\"Amazing! Are you psychic?\"" msgstr "\"Amazing! Are you psychic?\"" +#. https://poeditor.com/projects/view_terms?id=490053&search=pages.CopyingDictionaries.steps.making_copies +#. +#. d1 = {'a': 1, 'b': 2} +#. d2 = d1.copy() # Create a separate copy +#. +#. print("d1 before:", d1) +#. print("d2 before:", d2) +#. print("Are they the same object?", d1 is d2) +#. +#. d2['c'] = 3 # Modify the copy +#. +#. print("d1 after:", d1) # Is d1 affected now? +#. print("d2 after:", d2) +#. +#. ------ +#. +#. https://poeditor.com/projects/view_terms?id=490053&search=pages.CopyingDictionaries.steps.shared_references +#. +#. d1 = {'a': 1, 'b': 2} +#. d2 = d1 +#. +#. print("d1 before:", d1) +#. print("d2 before:", d2) +#. print("Are they the same object?", d1 is d2) +#. +#. d2['c'] = 3 # Modify via d2 +#. +#. print("d1 after:", d1) # Is d1 affected? +#. print("d2 after:", d2) +msgid "code_bits.\"Are they the same object?\"" +msgstr "\"Are they the same object?\"" + #. https://poeditor.com/projects/view_terms?id=490053&search=pages.DefiningFunctions.steps.change_function_name #. #. def say_hello(name): @@ -1372,6 +1404,134 @@ msgstr "\"abc\"" msgid "code_bits.\"cat.jpg\"" msgstr "\"cat.jpg\"" +#. https://poeditor.com/projects/view_terms?id=490053&search=pages.CopyingDictionaries.steps.making_copies +#. +#. d1 = {'a': 1, 'b': 2} +#. d2 = d1.copy() # Create a separate copy +#. +#. print("d1 before:", d1) +#. print("d2 before:", d2) +#. print("Are they the same object?", d1 is d2) +#. +#. d2['c'] = 3 # Modify the copy +#. +#. print("d1 after:", d1) # Is d1 affected now? +#. print("d2 after:", d2) +#. +#. ------ +#. +#. https://poeditor.com/projects/view_terms?id=490053&search=pages.CopyingDictionaries.steps.shared_references +#. +#. d1 = {'a': 1, 'b': 2} +#. d2 = d1 +#. +#. print("d1 before:", d1) +#. print("d2 before:", d2) +#. print("Are they the same object?", d1 is d2) +#. +#. d2['c'] = 3 # Modify via d2 +#. +#. print("d1 after:", d1) # Is d1 affected? +#. print("d2 after:", d2) +msgid "code_bits.\"d1 after:\"" +msgstr "\"d1 after:\"" + +#. https://poeditor.com/projects/view_terms?id=490053&search=pages.CopyingDictionaries.steps.making_copies +#. +#. d1 = {'a': 1, 'b': 2} +#. d2 = d1.copy() # Create a separate copy +#. +#. print("d1 before:", d1) +#. print("d2 before:", d2) +#. print("Are they the same object?", d1 is d2) +#. +#. d2['c'] = 3 # Modify the copy +#. +#. print("d1 after:", d1) # Is d1 affected now? +#. print("d2 after:", d2) +#. +#. ------ +#. +#. https://poeditor.com/projects/view_terms?id=490053&search=pages.CopyingDictionaries.steps.shared_references +#. +#. d1 = {'a': 1, 'b': 2} +#. d2 = d1 +#. +#. print("d1 before:", d1) +#. print("d2 before:", d2) +#. print("Are they the same object?", d1 is d2) +#. +#. d2['c'] = 3 # Modify via d2 +#. +#. print("d1 after:", d1) # Is d1 affected? +#. print("d2 after:", d2) +msgid "code_bits.\"d1 before:\"" +msgstr "\"d1 before:\"" + +#. https://poeditor.com/projects/view_terms?id=490053&search=pages.CopyingDictionaries.steps.making_copies +#. +#. d1 = {'a': 1, 'b': 2} +#. d2 = d1.copy() # Create a separate copy +#. +#. print("d1 before:", d1) +#. print("d2 before:", d2) +#. print("Are they the same object?", d1 is d2) +#. +#. d2['c'] = 3 # Modify the copy +#. +#. print("d1 after:", d1) # Is d1 affected now? +#. print("d2 after:", d2) +#. +#. ------ +#. +#. https://poeditor.com/projects/view_terms?id=490053&search=pages.CopyingDictionaries.steps.shared_references +#. +#. d1 = {'a': 1, 'b': 2} +#. d2 = d1 +#. +#. print("d1 before:", d1) +#. print("d2 before:", d2) +#. print("Are they the same object?", d1 is d2) +#. +#. d2['c'] = 3 # Modify via d2 +#. +#. print("d1 after:", d1) # Is d1 affected? +#. print("d2 after:", d2) +msgid "code_bits.\"d2 after:\"" +msgstr "\"d2 after:\"" + +#. https://poeditor.com/projects/view_terms?id=490053&search=pages.CopyingDictionaries.steps.making_copies +#. +#. d1 = {'a': 1, 'b': 2} +#. d2 = d1.copy() # Create a separate copy +#. +#. print("d1 before:", d1) +#. print("d2 before:", d2) +#. print("Are they the same object?", d1 is d2) +#. +#. d2['c'] = 3 # Modify the copy +#. +#. print("d1 after:", d1) # Is d1 affected now? +#. print("d2 after:", d2) +#. +#. ------ +#. +#. https://poeditor.com/projects/view_terms?id=490053&search=pages.CopyingDictionaries.steps.shared_references +#. +#. d1 = {'a': 1, 'b': 2} +#. d2 = d1 +#. +#. print("d1 before:", d1) +#. print("d2 before:", d2) +#. print("Are they the same object?", d1 is d2) +#. +#. d2['c'] = 3 # Modify via d2 +#. +#. print("d1 after:", d1) # Is d1 affected? +#. print("d2 after:", d2) +msgid "code_bits.\"d2 before:\"" +msgstr "\"d2 before:\"" + #. https://poeditor.com/projects/view_terms?id=490053&search=pages.IntroducingNestedLists.steps.double_subscripting #. #. strings = ["abc", "def", "ghi"] @@ -3296,6 +3456,44 @@ msgstr "'aeiou'" msgid "code_bits.'apfel'" msgstr "'apfel'" +#. https://poeditor.com/projects/view_terms?id=490053&search=pages.CopyingDictionaries.steps.add_item_exercise.text +#. +#. def add_item(item, quantities): +#. # Your code here +#. ... +#. +#. stock = {'apple': 5, 'banana': 2} +#. new_stock = add_item('apple', stock) +#. assert_equal(stock, {'apple': 5, 'banana': 2}) # Original unchanged +#. assert_equal(new_stock, {'apple': 6, 'banana': 2}) # Copy has incremented value +#. +#. new_stock_2 = add_item('banana', new_stock) +#. assert_equal(new_stock, {'apple': 6, 'banana': 2}) # Previous copy unchanged +#. assert_equal(new_stock_2, {'apple': 6, 'banana': 3}) # New copy incremented +#. +#. ------ +#. +#. https://poeditor.com/projects/view_terms?id=490053&search=pages.CopyingDictionaries.steps.positive_stock_exercise.text +#. +#. def positive_stock(stock): +#. # Your code here +#. ... +#. +#. assert_equal( +#. positive_stock({'apple': 10, 'banana': 0, 'pear': 5, 'orange': 0}), +#. {'apple': 10, 'pear': 5} +#. ) +#. assert_equal( +#. positive_stock({'pen': 0, 'pencil': 0}), +#. {} +#. ) +#. assert_equal( +#. positive_stock({'book': 1, 'paper': 5}), +#. {'book': 1, 'paper': 5} +#. ) +#. +#. ------ +#. #. https://poeditor.com/projects/view_terms?id=490053&search=pages.CreatingKeyValuePairs.steps.make_english_to_german_exercise.text #. #. def make_english_to_german(english_to_french, french_to_german): @@ -3502,6 +3700,44 @@ msgstr "'apple'" msgid "code_bits.'are'" msgstr "'are'" +#. https://poeditor.com/projects/view_terms?id=490053&search=pages.CopyingDictionaries.steps.add_item_exercise.text +#. +#. def add_item(item, quantities): +#. # Your code here +#. ... +#. +#. stock = {'apple': 5, 'banana': 2} +#. new_stock = add_item('apple', stock) +#. assert_equal(stock, {'apple': 5, 'banana': 2}) # Original unchanged +#. assert_equal(new_stock, {'apple': 6, 'banana': 2}) # Copy has incremented value +#. +#. new_stock_2 = add_item('banana', new_stock) +#. assert_equal(new_stock, {'apple': 6, 'banana': 2}) # Previous copy unchanged +#. assert_equal(new_stock_2, {'apple': 6, 'banana': 3}) # New copy incremented +#. +#. ------ +#. +#. https://poeditor.com/projects/view_terms?id=490053&search=pages.CopyingDictionaries.steps.positive_stock_exercise.text +#. +#. def positive_stock(stock): +#. # Your code here +#. ... +#. +#. assert_equal( +#. positive_stock({'apple': 10, 'banana': 0, 'pear': 5, 'orange': 0}), +#. {'apple': 10, 'pear': 5} +#. ) +#. assert_equal( +#. positive_stock({'pen': 0, 'pencil': 0}), +#. {} +#. ) +#. assert_equal( +#. positive_stock({'book': 1, 'paper': 5}), +#. {'book': 1, 'paper': 5} +#. ) +msgid "code_bits.'banana'" +msgstr "'banana'" + #. https://poeditor.com/projects/view_terms?id=490053&search=pages.TheEqualityOperator.steps.introducing_equality #. #. print(1 + 2 == 3) @@ -3588,6 +3824,27 @@ msgstr "'bc'" msgid "code_bits.'boite'" msgstr "'boite'" +#. https://poeditor.com/projects/view_terms?id=490053&search=pages.CopyingDictionaries.steps.positive_stock_exercise.text +#. +#. def positive_stock(stock): +#. # Your code here +#. ... +#. +#. assert_equal( +#. positive_stock({'apple': 10, 'banana': 0, 'pear': 5, 'orange': 0}), +#. {'apple': 10, 'pear': 5} +#. ) +#. assert_equal( +#. positive_stock({'pen': 0, 'pencil': 0}), +#. {} +#. ) +#. assert_equal( +#. positive_stock({'book': 1, 'paper': 5}), +#. {'book': 1, 'paper': 5} +#. ) +msgid "code_bits.'book'" +msgstr "'book'" + #. https://poeditor.com/projects/view_terms?id=490053&search=pages.CreatingKeyValuePairs.steps.dict_assignment_valid #. #. quantities = {} @@ -4469,6 +4726,111 @@ msgstr "'list'" msgid "code_bits.'on'" msgstr "'on'" +#. https://poeditor.com/projects/view_terms?id=490053&search=pages.CopyingDictionaries.steps.positive_stock_exercise.text +#. +#. def positive_stock(stock): +#. # Your code here +#. ... +#. +#. assert_equal( +#. positive_stock({'apple': 10, 'banana': 0, 'pear': 5, 'orange': 0}), +#. {'apple': 10, 'pear': 5} +#. ) +#. assert_equal( +#. positive_stock({'pen': 0, 'pencil': 0}), +#. {} +#. ) +#. assert_equal( +#. positive_stock({'book': 1, 'paper': 5}), +#. {'book': 1, 'paper': 5} +#. ) +msgid "code_bits.'orange'" +msgstr "'orange'" + +#. https://poeditor.com/projects/view_terms?id=490053&search=pages.CopyingDictionaries.steps.positive_stock_exercise.text +#. +#. def positive_stock(stock): +#. # Your code here +#. ... +#. +#. assert_equal( +#. positive_stock({'apple': 10, 'banana': 0, 'pear': 5, 'orange': 0}), +#. {'apple': 10, 'pear': 5} +#. ) +#. assert_equal( +#. positive_stock({'pen': 0, 'pencil': 0}), +#. {} +#. ) +#. assert_equal( +#. positive_stock({'book': 1, 'paper': 5}), +#. {'book': 1, 'paper': 5} +#. ) +msgid "code_bits.'paper'" +msgstr "'paper'" + +#. https://poeditor.com/projects/view_terms?id=490053&search=pages.CopyingDictionaries.steps.positive_stock_exercise.text +#. +#. def positive_stock(stock): +#. # Your code here +#. ... +#. +#. assert_equal( +#. positive_stock({'apple': 10, 'banana': 0, 'pear': 5, 'orange': 0}), +#. {'apple': 10, 'pear': 5} +#. ) +#. assert_equal( +#. positive_stock({'pen': 0, 'pencil': 0}), +#. {} +#. ) +#. assert_equal( +#. positive_stock({'book': 1, 'paper': 5}), +#. {'book': 1, 'paper': 5} +#. ) +msgid "code_bits.'pear'" +msgstr "'pear'" + +#. https://poeditor.com/projects/view_terms?id=490053&search=pages.CopyingDictionaries.steps.positive_stock_exercise.text +#. +#. def positive_stock(stock): +#. # Your code here +#. ... +#. +#. assert_equal( +#. positive_stock({'apple': 10, 'banana': 0, 'pear': 5, 'orange': 0}), +#. {'apple': 10, 'pear': 5} +#. ) +#. assert_equal( +#. positive_stock({'pen': 0, 'pencil': 0}), +#. {} +#. ) +#. assert_equal( +#. positive_stock({'book': 1, 'paper': 5}), +#. {'book': 1, 'paper': 5} +#. ) +msgid "code_bits.'pen'" +msgstr "'pen'" + +#. https://poeditor.com/projects/view_terms?id=490053&search=pages.CopyingDictionaries.steps.positive_stock_exercise.text +#. +#. def positive_stock(stock): +#. # Your code here +#. ... +#. +#. assert_equal( +#. positive_stock({'apple': 10, 'banana': 0, 'pear': 5, 'orange': 0}), +#. {'apple': 10, 'pear': 5} +#. ) +#. assert_equal( +#. positive_stock({'pen': 0, 'pencil': 0}), +#. {} +#. ) +#. assert_equal( +#. positive_stock({'book': 1, 'paper': 5}), +#. {'book': 1, 'paper': 5} +#. ) +msgid "code_bits.'pencil'" +msgstr "'pencil'" + #. https://poeditor.com/projects/view_terms?id=490053&search=pages.CreatingKeyValuePairs.steps.make_english_to_german_exercise.text #. #. def make_english_to_german(english_to_french, french_to_german): @@ -4650,6 +5012,18 @@ msgstr "'you'" msgid "code_bits.Hello" msgstr "Hello" +#. https://poeditor.com/projects/view_terms?id=490053&search=pages.CopyingDictionaries.steps.making_copies.text +#. +#. __program_indented__ +#. +#. ------ +#. +#. https://poeditor.com/projects/view_terms?id=490053&search=pages.CopyingDictionaries.steps.shared_references.text +#. +#. __program_indented__ +#. +#. ------ +#. #. https://poeditor.com/projects/view_terms?id=490053&search=pages.CreatingKeyValuePairs.steps.dict_assignment_valid.text #. #. __program_indented__ @@ -4960,6 +5334,32 @@ msgstr "__program_indented__" msgid "code_bits.actual" msgstr "actual" +#. https://poeditor.com/projects/view_terms?id=490053&search=pages.CopyingDictionaries.steps.add_item_exercise +#. +#. def add_item(item, quantities): +#. new_quantities = quantities.copy() +#. new_quantities[item] = new_quantities[item] + 1 +#. return new_quantities +#. +#. ------ +#. +#. https://poeditor.com/projects/view_terms?id=490053&search=pages.CopyingDictionaries.steps.add_item_exercise.text +#. +#. def add_item(item, quantities): +#. # Your code here +#. ... +#. +#. stock = {'apple': 5, 'banana': 2} +#. new_stock = add_item('apple', stock) +#. assert_equal(stock, {'apple': 5, 'banana': 2}) # Original unchanged +#. assert_equal(new_stock, {'apple': 6, 'banana': 2}) # Copy has incremented value +#. +#. new_stock_2 = add_item('banana', new_stock) +#. assert_equal(new_stock, {'apple': 6, 'banana': 2}) # Previous copy unchanged +#. assert_equal(new_stock_2, {'apple': 6, 'banana': 3}) # New copy incremented +msgid "code_bits.add_item" +msgstr "add_item" + #. https://poeditor.com/projects/view_terms?id=490053&search=pages.IntroducingFstrings.steps.basic_f_string_exercise #. #. name = "Alice" @@ -5157,6 +5557,44 @@ msgstr "all_numbers" #. #. ------ #. +#. https://poeditor.com/projects/view_terms?id=490053&search=pages.CopyingDictionaries.steps.add_item_exercise.text +#. +#. def add_item(item, quantities): +#. # Your code here +#. ... +#. +#. stock = {'apple': 5, 'banana': 2} +#. new_stock = add_item('apple', stock) +#. assert_equal(stock, {'apple': 5, 'banana': 2}) # Original unchanged +#. assert_equal(new_stock, {'apple': 6, 'banana': 2}) # Copy has incremented value +#. +#. new_stock_2 = add_item('banana', new_stock) +#. assert_equal(new_stock, {'apple': 6, 'banana': 2}) # Previous copy unchanged +#. assert_equal(new_stock_2, {'apple': 6, 'banana': 3}) # New copy incremented +#. +#. ------ +#. +#. https://poeditor.com/projects/view_terms?id=490053&search=pages.CopyingDictionaries.steps.positive_stock_exercise.text +#. +#. def positive_stock(stock): +#. # Your code here +#. ... +#. +#. assert_equal( +#. positive_stock({'apple': 10, 'banana': 0, 'pear': 5, 'orange': 0}), +#. {'apple': 10, 'pear': 5} +#. ) +#. assert_equal( +#. positive_stock({'pen': 0, 'pencil': 0}), +#. {} +#. ) +#. assert_equal( +#. positive_stock({'book': 1, 'paper': 5}), +#. {'book': 1, 'paper': 5} +#. ) +#. +#. ------ +#. #. https://poeditor.com/projects/view_terms?id=490053&search=pages.CreatingKeyValuePairs.steps.make_english_to_german_exercise.text #. #. def make_english_to_german(english_to_french, french_to_german): @@ -8208,6 +8646,70 @@ msgstr "consonants" msgid "code_bits.cube" msgstr "cube" +#. https://poeditor.com/projects/view_terms?id=490053&search=pages.CopyingDictionaries.steps.making_copies +#. +#. d1 = {'a': 1, 'b': 2} +#. d2 = d1.copy() # Create a separate copy +#. +#. print("d1 before:", d1) +#. print("d2 before:", d2) +#. print("Are they the same object?", d1 is d2) +#. +#. d2['c'] = 3 # Modify the copy +#. +#. print("d1 after:", d1) # Is d1 affected now? +#. print("d2 after:", d2) +#. +#. ------ +#. +#. https://poeditor.com/projects/view_terms?id=490053&search=pages.CopyingDictionaries.steps.shared_references +#. +#. d1 = {'a': 1, 'b': 2} +#. d2 = d1 +#. +#. print("d1 before:", d1) +#. print("d2 before:", d2) +#. print("Are they the same object?", d1 is d2) +#. +#. d2['c'] = 3 # Modify via d2 +#. +#. print("d1 after:", d1) # Is d1 affected? +#. print("d2 after:", d2) +msgid "code_bits.d1" +msgstr "d1" + +#. https://poeditor.com/projects/view_terms?id=490053&search=pages.CopyingDictionaries.steps.making_copies +#. +#. d1 = {'a': 1, 'b': 2} +#. d2 = d1.copy() # Create a separate copy +#. +#. print("d1 before:", d1) +#. print("d2 before:", d2) +#. print("Are they the same object?", d1 is d2) +#. +#. d2['c'] = 3 # Modify the copy +#. +#. print("d1 after:", d1) # Is d1 affected now? +#. print("d2 after:", d2) +#. +#. ------ +#. +#. https://poeditor.com/projects/view_terms?id=490053&search=pages.CopyingDictionaries.steps.shared_references +#. +#. d1 = {'a': 1, 'b': 2} +#. d2 = d1 +#. +#. print("d1 before:", d1) +#. print("d2 before:", d2) +#. print("Are they the same object?", d1 is d2) +#. +#. d2['c'] = 3 # Modify via d2 +#. +#. print("d1 after:", d1) # Is d1 affected? +#. print("d2 after:", d2) +msgid "code_bits.d2" +msgstr "d2" + #. https://poeditor.com/projects/view_terms?id=490053&search=pages.CombiningAndAndOr.steps.final_text.text #. #. diagonal1 = all_equal([board[0][0], board[1][1], board[2][2]]) @@ -11348,6 +11850,44 @@ msgstr "is_friend" msgid "code_bits.is_valid_percentage" msgstr "is_valid_percentage" +#. https://poeditor.com/projects/view_terms?id=490053&search=pages.CopyingDictionaries.steps.add_item_exercise +#. +#. def add_item(item, quantities): +#. new_quantities = quantities.copy() +#. new_quantities[item] = new_quantities[item] + 1 +#. return new_quantities +#. +#. ------ +#. +#. https://poeditor.com/projects/view_terms?id=490053&search=pages.CopyingDictionaries.steps.add_item_exercise.text +#. +#. def add_item(item, quantities): +#. # Your code here +#. ... +#. +#. stock = {'apple': 5, 'banana': 2} +#. new_stock = add_item('apple', stock) +#. assert_equal(stock, {'apple': 5, 'banana': 2}) # Original unchanged +#. assert_equal(new_stock, {'apple': 6, 'banana': 2}) # Copy has incremented value +#. +#. new_stock_2 = add_item('banana', new_stock) +#. assert_equal(new_stock, {'apple': 6, 'banana': 2}) # Previous copy unchanged +#. assert_equal(new_stock_2, {'apple': 6, 'banana': 3}) # New copy incremented +#. +#. ------ +#. +#. https://poeditor.com/projects/view_terms?id=490053&search=pages.CopyingDictionaries.steps.positive_stock_exercise +#. +#. def positive_stock(stock): +#. result = {} +#. for item in stock: +#. quantity = stock[item] +#. if quantity > 0: +#. result[item] = quantity +#. return result +#. +#. ------ +#. #. https://poeditor.com/projects/view_terms?id=490053&search=pages.CreatingKeyValuePairs.steps.buy_quantity_exercise #. #. def buy_quantity(quantities): @@ -13312,6 +13852,15 @@ msgstr "new_numbers" msgid "code_bits.new_nums" msgstr "new_nums" +#. https://poeditor.com/projects/view_terms?id=490053&search=pages.CopyingDictionaries.steps.add_item_exercise +#. +#. def add_item(item, quantities): +#. new_quantities = quantities.copy() +#. new_quantities[item] = new_quantities[item] + 1 +#. return new_quantities +msgid "code_bits.new_quantities" +msgstr "new_quantities" + #. https://poeditor.com/projects/view_terms?id=490053&search=pages.CombiningCompoundStatements.steps.final_text.text #. #. sentence = 'Hello World' @@ -13442,6 +13991,40 @@ msgstr "new_nums" msgid "code_bits.new_sentence" msgstr "new_sentence" +#. https://poeditor.com/projects/view_terms?id=490053&search=pages.CopyingDictionaries.steps.add_item_exercise.text +#. +#. def add_item(item, quantities): +#. # Your code here +#. ... +#. +#. stock = {'apple': 5, 'banana': 2} +#. new_stock = add_item('apple', stock) +#. assert_equal(stock, {'apple': 5, 'banana': 2}) # Original unchanged +#. assert_equal(new_stock, {'apple': 6, 'banana': 2}) # Copy has incremented value +#. +#. new_stock_2 = add_item('banana', new_stock) +#. assert_equal(new_stock, {'apple': 6, 'banana': 2}) # Previous copy unchanged +#. assert_equal(new_stock_2, {'apple': 6, 'banana': 3}) # New copy incremented +msgid "code_bits.new_stock" +msgstr "new_stock" + +#. https://poeditor.com/projects/view_terms?id=490053&search=pages.CopyingDictionaries.steps.add_item_exercise.text +#. +#. def add_item(item, quantities): +#. # Your code here +#. ... +#. +#. stock = {'apple': 5, 'banana': 2} +#. new_stock = add_item('apple', stock) +#. assert_equal(stock, {'apple': 5, 'banana': 2}) # Original unchanged +#. assert_equal(new_stock, {'apple': 6, 'banana': 2}) # Copy has incremented value +#. +#. new_stock_2 = add_item('banana', new_stock) +#. assert_equal(new_stock, {'apple': 6, 'banana': 2}) # Previous copy unchanged +#. assert_equal(new_stock_2, {'apple': 6, 'banana': 3}) # New copy incremented +msgid "code_bits.new_stock_2" +msgstr "new_stock_2" + #. https://poeditor.com/projects/view_terms?id=490053&search=pages.FunctionsAndMethodsForLists.steps.subscript_assignment_predict.text #. #. some_list[index] = new_value @@ -15099,6 +15682,39 @@ msgstr "player2" msgid "code_bits.players" msgstr "players" +#. https://poeditor.com/projects/view_terms?id=490053&search=pages.CopyingDictionaries.steps.positive_stock_exercise +#. +#. def positive_stock(stock): +#. result = {} +#. for item in stock: +#. quantity = stock[item] +#. if quantity > 0: +#. result[item] = quantity +#. return result +#. +#. ------ +#. +#. https://poeditor.com/projects/view_terms?id=490053&search=pages.CopyingDictionaries.steps.positive_stock_exercise.text +#. +#. def positive_stock(stock): +#. # Your code here +#. ... +#. +#. assert_equal( +#. positive_stock({'apple': 10, 'banana': 0, 'pear': 5, 'orange': 0}), +#. {'apple': 10, 'pear': 5} +#. ) +#. assert_equal( +#. positive_stock({'pen': 0, 'pencil': 0}), +#. {} +#. ) +#. assert_equal( +#. positive_stock({'book': 1, 'paper': 5}), +#. {'book': 1, 'paper': 5} +#. ) +msgid "code_bits.positive_stock" +msgstr "positive_stock" + #. https://poeditor.com/projects/view_terms?id=490053&search=pages.LoopingOverNestedLists.steps.list_contains_word_exercise #. #. strings = [['hello there', 'how are you'], ['goodbye world', 'hello world']] @@ -15858,6 +16474,32 @@ msgstr "printed" msgid "code_bits.quadruple" msgstr "quadruple" +#. https://poeditor.com/projects/view_terms?id=490053&search=pages.CopyingDictionaries.steps.add_item_exercise +#. +#. def add_item(item, quantities): +#. new_quantities = quantities.copy() +#. new_quantities[item] = new_quantities[item] + 1 +#. return new_quantities +#. +#. ------ +#. +#. https://poeditor.com/projects/view_terms?id=490053&search=pages.CopyingDictionaries.steps.add_item_exercise.text +#. +#. def add_item(item, quantities): +#. # Your code here +#. ... +#. +#. stock = {'apple': 5, 'banana': 2} +#. new_stock = add_item('apple', stock) +#. assert_equal(stock, {'apple': 5, 'banana': 2}) # Original unchanged +#. assert_equal(new_stock, {'apple': 6, 'banana': 2}) # Copy has incremented value +#. +#. new_stock_2 = add_item('banana', new_stock) +#. assert_equal(new_stock, {'apple': 6, 'banana': 2}) # Previous copy unchanged +#. assert_equal(new_stock_2, {'apple': 6, 'banana': 3}) # New copy incremented +#. +#. ------ +#. #. https://poeditor.com/projects/view_terms?id=490053&search=pages.CreatingKeyValuePairs.steps.buy_quantity_exercise #. #. def buy_quantity(quantities): @@ -16002,6 +16644,18 @@ msgstr "quadruple" msgid "code_bits.quantities" msgstr "quantities" +#. https://poeditor.com/projects/view_terms?id=490053&search=pages.CopyingDictionaries.steps.positive_stock_exercise +#. +#. def positive_stock(stock): +#. result = {} +#. for item in stock: +#. quantity = stock[item] +#. if quantity > 0: +#. result[item] = quantity +#. return result +#. +#. ------ +#. #. https://poeditor.com/projects/view_terms?id=490053&search=pages.DictionaryKeysAndValues.steps.cleanup_shopping_cart #. #. def total_cost(quantities, prices): @@ -16078,6 +16732,18 @@ msgstr "quantity" msgid "code_bits.quantity_str" msgstr "quantity_str" +#. https://poeditor.com/projects/view_terms?id=490053&search=pages.CopyingDictionaries.steps.positive_stock_exercise +#. +#. def positive_stock(stock): +#. result = {} +#. for item in stock: +#. quantity = stock[item] +#. if quantity > 0: +#. result[item] = quantity +#. return result +#. +#. ------ +#. #. https://poeditor.com/projects/view_terms?id=490053&search=pages.DictionaryKeysAndValues.steps.cleanup_shopping_cart #. #. def total_cost(quantities, prices): @@ -17771,6 +18437,56 @@ msgstr "some_list" msgid "code_bits.spaces" msgstr "spaces" +#. https://poeditor.com/projects/view_terms?id=490053&search=pages.CopyingDictionaries.steps.add_item_exercise.text +#. +#. def add_item(item, quantities): +#. # Your code here +#. ... +#. +#. stock = {'apple': 5, 'banana': 2} +#. new_stock = add_item('apple', stock) +#. assert_equal(stock, {'apple': 5, 'banana': 2}) # Original unchanged +#. assert_equal(new_stock, {'apple': 6, 'banana': 2}) # Copy has incremented value +#. +#. new_stock_2 = add_item('banana', new_stock) +#. assert_equal(new_stock, {'apple': 6, 'banana': 2}) # Previous copy unchanged +#. assert_equal(new_stock_2, {'apple': 6, 'banana': 3}) # New copy incremented +#. +#. ------ +#. +#. https://poeditor.com/projects/view_terms?id=490053&search=pages.CopyingDictionaries.steps.positive_stock_exercise +#. +#. def positive_stock(stock): +#. result = {} +#. for item in stock: +#. quantity = stock[item] +#. if quantity > 0: +#. result[item] = quantity +#. return result +#. +#. ------ +#. +#. https://poeditor.com/projects/view_terms?id=490053&search=pages.CopyingDictionaries.steps.positive_stock_exercise.text +#. +#. def positive_stock(stock): +#. # Your code here +#. ... +#. +#. assert_equal( +#. positive_stock({'apple': 10, 'banana': 0, 'pear': 5, 'orange': 0}), +#. {'apple': 10, 'pear': 5} +#. ) +#. assert_equal( +#. positive_stock({'pen': 0, 'pencil': 0}), +#. {} +#. ) +#. assert_equal( +#. positive_stock({'book': 1, 'paper': 5}), +#. {'book': 1, 'paper': 5} +#. ) +msgid "code_bits.stock" +msgstr "stock" + #. https://poeditor.com/projects/view_terms?id=490053&search=pages.IntroducingNestedLists.steps.double_subscripting.text #. #. string = strings[1] @@ -22218,6 +22934,283 @@ msgstr "" msgid "pages.CombiningCompoundStatements.title" msgstr "Combining Compound Statements" +#. https://futurecoder.io/course/#CopyingDictionaries +#. +#. https://poeditor.com/projects/view_terms?id=490053&search=pages.CopyingDictionaries.steps.add_item_exercise +msgid "pages.CopyingDictionaries.steps.add_item_exercise.hints.0.text" +msgstr "" +"First, create a *copy* of the input `quantities` dictionary using the `.copy()` method. Store this in a new variable, " +"e.g., `new_quantities`." + +#. https://futurecoder.io/course/#CopyingDictionaries +#. +#. https://poeditor.com/projects/view_terms?id=490053&search=pages.CopyingDictionaries.steps.add_item_exercise +msgid "pages.CopyingDictionaries.steps.add_item_exercise.hints.1.text" +msgstr "Since we assume `item` is already a key, you don't need to check for its existence in this exercise." + +#. https://futurecoder.io/course/#CopyingDictionaries +#. +#. https://poeditor.com/projects/view_terms?id=490053&search=pages.CopyingDictionaries.steps.add_item_exercise +msgid "pages.CopyingDictionaries.steps.add_item_exercise.hints.2.text" +msgstr "Find the current quantity of the `item` in the `new_quantities` copy using `new_quantities[item]`." + +#. https://futurecoder.io/course/#CopyingDictionaries +#. +#. https://poeditor.com/projects/view_terms?id=490053&search=pages.CopyingDictionaries.steps.add_item_exercise +msgid "pages.CopyingDictionaries.steps.add_item_exercise.hints.3.text" +msgstr "Calculate the new quantity by adding 1 to the current quantity." + +#. https://futurecoder.io/course/#CopyingDictionaries +#. +#. https://poeditor.com/projects/view_terms?id=490053&search=pages.CopyingDictionaries.steps.add_item_exercise +msgid "pages.CopyingDictionaries.steps.add_item_exercise.hints.4.text" +msgstr "" +"Update the value for `item` in the `new_quantities` copy with this new quantity using assignment: " +"`new_quantities[item] = ...`." + +#. https://futurecoder.io/course/#CopyingDictionaries +#. +#. https://poeditor.com/projects/view_terms?id=490053&search=pages.CopyingDictionaries.steps.add_item_exercise +msgid "pages.CopyingDictionaries.steps.add_item_exercise.hints.5.text" +msgstr "Return the `new_quantities` dictionary." + +#. https://futurecoder.io/course/#CopyingDictionaries +#. +#. # __code0__: +#. def add_item(item, quantities): +#. # Your code here +#. ... +#. +#. stock = {'apple': 5, 'banana': 2} +#. new_stock = add_item('apple', stock) +#. assert_equal(stock, {'apple': 5, 'banana': 2}) # Original unchanged +#. assert_equal(new_stock, {'apple': 6, 'banana': 2}) # Copy has incremented value +#. +#. new_stock_2 = add_item('banana', new_stock) +#. assert_equal(new_stock, {'apple': 6, 'banana': 2}) # Previous copy unchanged +#. assert_equal(new_stock_2, {'apple': 6, 'banana': 3}) # New copy incremented +#. +#. https://poeditor.com/projects/view_terms?id=490053&search=code_bits.%27apple%27 +#. +#. https://poeditor.com/projects/view_terms?id=490053&search=code_bits.%27banana%27 +#. +#. https://poeditor.com/projects/view_terms?id=490053&search=code_bits.add_item +#. +#. https://poeditor.com/projects/view_terms?id=490053&search=code_bits.assert_equal +#. +#. https://poeditor.com/projects/view_terms?id=490053&search=code_bits.item +#. +#. https://poeditor.com/projects/view_terms?id=490053&search=code_bits.new_stock +#. +#. https://poeditor.com/projects/view_terms?id=490053&search=code_bits.new_stock_2 +#. +#. https://poeditor.com/projects/view_terms?id=490053&search=code_bits.quantities +#. +#. https://poeditor.com/projects/view_terms?id=490053&search=code_bits.stock +msgid "pages.CopyingDictionaries.steps.add_item_exercise.text" +msgstr "" +"Let's practice combining copying and modifying. Imagine we want to represent adding one unit of an item to our stock count.\n" +"\n" +"Write a function `add_item(item, quantities)` that takes an item name (`item`) and a dictionary `quantities`. You can assume the `item` *already exists* as a key in the `quantities` dictionary.\n" +"\n" +"The function should return a *new* dictionary which is a copy of `quantities`, but with the value associated with `item` increased by 1. The original `quantities` dictionary should not be changed.\n" +"\n" +" __copyable__\n" +"__code0__" + +#. https://futurecoder.io/course/#CopyingDictionaries +msgid "pages.CopyingDictionaries.steps.final_text.text" +msgstr "" +"Great! You now know why copying dictionaries is important (because they are mutable) and how to do it using `.copy()`. You've also practiced creating modified copies, which is a common and safe way to work with data without accidentally changing things elsewhere in your program.\n" +"\n" +"Next, we'll see how to check if a key exists *before* trying to use it, to avoid errors." + +#. https://poeditor.com/projects/view_terms?id=490053&search=pages.CopyingDictionaries.steps.making_copies +msgid "pages.CopyingDictionaries.steps.making_copies.output_prediction_choices.0" +msgstr "" +"d1 before: {'a': 1, 'b': 2}\n" +"d2 before: {'a': 1, 'b': 2}\n" +"Are they the same object? True\n" +"d1 after: {'a': 1, 'b': 2, 'c': 3}\n" +"d2 after: {'a': 1, 'b': 2, 'c': 3}" + +#. https://poeditor.com/projects/view_terms?id=490053&search=pages.CopyingDictionaries.steps.making_copies +msgid "pages.CopyingDictionaries.steps.making_copies.output_prediction_choices.1" +msgstr "" +"d1 before: {'a': 1, 'b': 2}\n" +"d2 before: {'a': 1, 'b': 2}\n" +"Are they the same object? False\n" +"d1 after: {'a': 1, 'b': 2, 'c': 3}\n" +"d2 after: {'a': 1, 'b': 2, 'c': 3}" + +#. https://poeditor.com/projects/view_terms?id=490053&search=pages.CopyingDictionaries.steps.making_copies +msgid "pages.CopyingDictionaries.steps.making_copies.output_prediction_choices.2" +msgstr "" +"d1 before: {'a': 1, 'b': 2}\n" +"d2 before: {'a': 1, 'b': 2}\n" +"Are they the same object? False\n" +"d1 after: {'a': 1, 'b': 2}\n" +"d2 after: {'a': 1, 'b': 2, 'c': 3}" + +#. https://futurecoder.io/course/#CopyingDictionaries +#. +#. # __code0__: +#. __program_indented__ +#. +#. https://poeditor.com/projects/view_terms?id=490053&search=code_bits.__program_indented__ +msgid "pages.CopyingDictionaries.steps.making_copies.text" +msgstr "" +"Because `d1` and `d2` referred to the exact same dictionary object (`d1 is d2` was `True`), changing it via `d2` also changed what `d1` saw.\n" +"\n" +"To get a *separate* dictionary with the same contents, use the `.copy()` method.\n" +"\n" +"Predict how using `.copy()` changes the outcome, then run this code:\n" +"\n" +" __copyable__\n" +"__code0__" + +#. https://futurecoder.io/course/#CopyingDictionaries +#. +#. https://poeditor.com/projects/view_terms?id=490053&search=pages.CopyingDictionaries.steps.positive_stock_exercise +msgid "pages.CopyingDictionaries.steps.positive_stock_exercise.hints.0.text" +msgstr "Start by creating a new empty dictionary, e.g., `result = {}`." + +#. https://futurecoder.io/course/#CopyingDictionaries +#. +#. https://poeditor.com/projects/view_terms?id=490053&search=pages.CopyingDictionaries.steps.positive_stock_exercise +msgid "pages.CopyingDictionaries.steps.positive_stock_exercise.hints.1.text" +msgstr "Loop through the keys of the input `stock` dictionary." + +#. https://futurecoder.io/course/#CopyingDictionaries +#. +#. https://poeditor.com/projects/view_terms?id=490053&search=pages.CopyingDictionaries.steps.positive_stock_exercise +msgid "pages.CopyingDictionaries.steps.positive_stock_exercise.hints.2.text" +msgstr "Inside the loop, get the `quantity` for the current `item` using `stock[item]`." + +#. https://futurecoder.io/course/#CopyingDictionaries +#. +#. https://poeditor.com/projects/view_terms?id=490053&search=pages.CopyingDictionaries.steps.positive_stock_exercise +msgid "pages.CopyingDictionaries.steps.positive_stock_exercise.hints.3.text" +msgstr "Use an `if` statement to check if `quantity > 0`." + +#. https://futurecoder.io/course/#CopyingDictionaries +#. +#. https://poeditor.com/projects/view_terms?id=490053&search=pages.CopyingDictionaries.steps.positive_stock_exercise +msgid "pages.CopyingDictionaries.steps.positive_stock_exercise.hints.4.text" +msgstr "" +"If the quantity is positive, add the `item` and its `quantity` to your `result` dictionary using `result[item] = " +"quantity`." + +#. https://futurecoder.io/course/#CopyingDictionaries +#. +#. https://poeditor.com/projects/view_terms?id=490053&search=pages.CopyingDictionaries.steps.positive_stock_exercise +msgid "pages.CopyingDictionaries.steps.positive_stock_exercise.hints.5.text" +msgstr "After the loop finishes, return the `result` dictionary." + +#. https://futurecoder.io/course/#CopyingDictionaries +#. +#. https://poeditor.com/projects/view_terms?id=490053&search=pages.CopyingDictionaries.steps.positive_stock_exercise +msgid "pages.CopyingDictionaries.steps.positive_stock_exercise.hints.6.text" +msgstr "" +"Make sure you don't modify the original `stock` dictionary passed into the function. Creating a new `result` " +"dictionary ensures this." + +#. https://futurecoder.io/course/#CopyingDictionaries +#. +#. # __code0__: +#. def positive_stock(stock): +#. # Your code here +#. ... +#. +#. assert_equal( +#. positive_stock({'apple': 10, 'banana': 0, 'pear': 5, 'orange': 0}), +#. {'apple': 10, 'pear': 5} +#. ) +#. assert_equal( +#. positive_stock({'pen': 0, 'pencil': 0}), +#. {} +#. ) +#. assert_equal( +#. positive_stock({'book': 1, 'paper': 5}), +#. {'book': 1, 'paper': 5} +#. ) +#. +#. https://poeditor.com/projects/view_terms?id=490053&search=code_bits.%27apple%27 +#. +#. https://poeditor.com/projects/view_terms?id=490053&search=code_bits.%27banana%27 +#. +#. https://poeditor.com/projects/view_terms?id=490053&search=code_bits.%27book%27 +#. +#. https://poeditor.com/projects/view_terms?id=490053&search=code_bits.%27orange%27 +#. +#. https://poeditor.com/projects/view_terms?id=490053&search=code_bits.%27paper%27 +#. +#. https://poeditor.com/projects/view_terms?id=490053&search=code_bits.%27pear%27 +#. +#. https://poeditor.com/projects/view_terms?id=490053&search=code_bits.%27pen%27 +#. +#. https://poeditor.com/projects/view_terms?id=490053&search=code_bits.%27pencil%27 +#. +#. https://poeditor.com/projects/view_terms?id=490053&search=code_bits.assert_equal +#. +#. https://poeditor.com/projects/view_terms?id=490053&search=code_bits.positive_stock +#. +#. https://poeditor.com/projects/view_terms?id=490053&search=code_bits.stock +msgid "pages.CopyingDictionaries.steps.positive_stock_exercise.text" +msgstr "" +"Making an exact copy is useful, but often we want a *modified* copy. Let's practice creating a new dictionary based on an old one.\n" +"\n" +"Write a function `positive_stock(stock)` that takes a dictionary `stock` (mapping item names to integer quantities) and returns a *new* dictionary containing only the items from the original `stock` where the quantity is strictly greater than 0. The original `stock` dictionary should not be changed.\n" +"\n" +" __copyable__\n" +"__code0__" + +#. https://poeditor.com/projects/view_terms?id=490053&search=pages.CopyingDictionaries.steps.shared_references +msgid "pages.CopyingDictionaries.steps.shared_references.output_prediction_choices.0" +msgstr "" +"d1 before: {'a': 1, 'b': 2}\n" +"d2 before: {'a': 1, 'b': 2}\n" +"Are they the same object? True\n" +"d1 after: {'a': 1, 'b': 2}\n" +"d2 after: {'a': 1, 'b': 2, 'c': 3}" + +#. https://poeditor.com/projects/view_terms?id=490053&search=pages.CopyingDictionaries.steps.shared_references +msgid "pages.CopyingDictionaries.steps.shared_references.output_prediction_choices.1" +msgstr "" +"d1 before: {'a': 1, 'b': 2}\n" +"d2 before: {'a': 1, 'b': 2}\n" +"Are they the same object? True\n" +"d1 after: {'a': 1, 'b': 2, 'c': 3}\n" +"d2 after: {'a': 1, 'b': 2, 'c': 3}" + +#. https://poeditor.com/projects/view_terms?id=490053&search=pages.CopyingDictionaries.steps.shared_references +msgid "pages.CopyingDictionaries.steps.shared_references.output_prediction_choices.2" +msgstr "" +"d1 before: {'a': 1, 'b': 2}\n" +"d2 before: {'a': 1, 'b': 2}\n" +"Are they the same object? False\n" +"d1 after: {'a': 1, 'b': 2}\n" +"d2 after: {'a': 1, 'b': 2, 'c': 3}" + +#. https://futurecoder.io/course/#CopyingDictionaries +#. +#. # __code0__: +#. __program_indented__ +#. +#. https://poeditor.com/projects/view_terms?id=490053&search=code_bits.__program_indented__ +msgid "pages.CopyingDictionaries.steps.shared_references.text" +msgstr "" +"Remember how assigning one list variable to another (`list2 = list1`) made both names point to the *same* list? Dictionaries work the same way because they are also *mutable* (can be changed).\n" +"\n" +"Predict what the following code will print, then run it to see:\n" +"\n" +" __copyable__\n" +"__code0__" + +#. https://futurecoder.io/course/#CopyingDictionaries +msgid "pages.CopyingDictionaries.title" +msgstr "Copying Dictionaries" + #. https://futurecoder.io/course/#CreatingKeyValuePairs #. #. https://poeditor.com/projects/view_terms?id=490053&search=pages.CreatingKeyValuePairs.steps.buy_quantity_exercise @@ -22318,7 +23311,8 @@ msgstr "" " {'dog': 5000000, 'box': 2}\n" "\n" "Note that `buy_quantity` should *modify* the dictionary that's passed in, and doesn't need to return anything.\n" -"You can assume that the user will enter a valid integer for the quantity." +"You can assume that the user will enter a valid integer for the quantity.\n" +"You can also assume that the user won't enter an item that's already in `quantities`." #. https://poeditor.com/projects/view_terms?id=490053&search=pages.CreatingKeyValuePairs.steps.dict_assignment_valid msgid "pages.CreatingKeyValuePairs.steps.dict_assignment_valid.output_prediction_choices.1" @@ -22373,7 +23367,7 @@ msgstr "" "some data will be lost.\n" "\n" "But there are many situations where you can be sure that the values in a dictionary *are* unique and that this\n" -"'inversion' makes sense. For example, we saw this code [earlier in the chapter](#UsingDictionariesInPractice):\n" +"'inversion' makes sense. For example, we saw this code [earlier in the chapter](#UsingDictionaries):\n" "\n" " __copyable__\n" " __no_auto_translate__\n" diff --git a/translations/locales/en/LC_MESSAGES/futurecoder.mo b/translations/locales/en/LC_MESSAGES/futurecoder.mo index 5b843e1d940c895c6dfe605d16bf2ddc52d054e0..14d74342357f6589a2158f7534cc816ef9345670 100644 GIT binary patch delta 32367 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 pFad - Phonifier reborn

Pfad - The Proxy pFad of © 2024 Garber Painting. All rights reserved.

Note: This service is not intended for secure transactions such as banking, social media, email, or purchasing. Use at your own risk. We assume no liability whatsoever for broken pages.


Alternative Proxies:

Alternative Proxy

pFad Proxy

pFad v3 Proxy

pFad v4 Proxy