diff --git a/.gitignore b/.gitignore index 5490b94..febebf6 100644 --- a/.gitignore +++ b/.gitignore @@ -16,3 +16,6 @@ data/test_reports/ # Local AI curation reports data/curation_reports/*.json + +# Local exam coverage audit packet +tmp/exam_coverage_audit/ diff --git a/README.md b/README.md index 4143571..63385d9 100644 --- a/README.md +++ b/README.md @@ -72,8 +72,8 @@ Official course files are still kept at their canonical paths under `materials/` ## Support This Project -This project was made by just one student, and the AI coding tools used to build and improve it cost real money. +This project was built by one student, and the AI agents/tools used to build it cost real money. -If this helped you and you want to buy me a coffee to say thank you, please do: +If it saved you time or stress, consider buying me a coffee as a thank-you: [Buy me a coffee](https://buymeacoffee.com/caspersimon) diff --git a/data/quality/current_sample_exam_coverage_report.md b/data/quality/current_sample_exam_coverage_report.md new file mode 100644 index 0000000..3d00ec2 --- /dev/null +++ b/data/quality/current_sample_exam_coverage_report.md @@ -0,0 +1,51 @@ +# Current Sample Final Coverage Audit + +## Summary + +- Exam: `sample-final-plus-answers` +- Question count: 24 +- Exact selectable matches found: 24/24 +- Score distribution: `3 => 24`, `2 => 0`, `1 => 0`, `0 => 0` +- Exact matches already in `recommended`: 10 +- Exact matches only in `additional`: 14 + +## Key Findings + +- The builder already contains an exact selectable `source_exam` item for every question in the current sample final. +- Discoverability is weaker than raw coverage: 14 of the 24 exact matches are hidden in `additional` rather than `recommended`. +- Several exact matches appear routed under topic cards that do not match the imported question topic labels. The most obvious examples are questions 1-2 (OOP questions currently under `Pandas Core Structures`) and questions 5-8 (Pandas/String-method questions mapped into string-heavy or other non-obvious cards). +- This makes the current dataset better as a hidden coverage corpus than as an easy-to-navigate student-facing cheat-sheet builder. + +## Question Map + +| Q | Imported topic label | Current card topic | Bucket | Evidence item id | +|---|---|---|---|---| +| 1 | OOP (Initializers) | Pandas Core Structures | recommended | `exam-intro_python_sample_final_24_25-1-w5-pandas-core-structures` | +| 2 | OOP (Methods) | Pandas Core Structures | recommended | `exam-intro_python_sample_final_24_25-2-w5-pandas-core-structures` | +| 3 | Dictionaries | Defining and Calling Functions | recommended | `exam-intro_python_sample_final_24_25-3-w3-defining-and-calling-functions` | +| 4 | String Methods | Conditions | additional | `exam-intro_python_sample_final_24_25-4-w2-conditions` | +| 5 | Pandas (Basic) | String Fundamentals | recommended | `exam-intro_python_sample_final_24_25-5-w4-string-fundamentals` | +| 6 | Pandas (Indexing) | String Operations and Methods | recommended | `exam-intro_python_sample_final_24_25-6-w4-string-operations-and-methods` | +| 7 | Pandas (Subset/Sort) | String Fundamentals | recommended | `exam-intro_python_sample_final_24_25-7-w4-string-fundamentals` | +| 8 | Pandas (Series Strings) | String Fundamentals | recommended | `exam-intro_python_sample_final_24_25-8-w4-string-fundamentals` | +| 9 | Datetime (Parsing) | Datetime | recommended | `exam-intro_python_sample_final_24_25-9-w6-datetime` | +| 10 | Datetime (Arithmetic) | Datetime | recommended | `exam-intro_python_sample_final_24_25-10-w6-datetime` | +| 11 | Comprehensions | Defining and Calling Functions | recommended | `exam-intro_python_sample_final_24_25-11-w3-defining-and-calling-functions` | +| 12 | List Comprehensions | Conditions | additional | `exam-intro_python_sample_final_24_25-12-w2-conditions` | +| 13 | Data Types | Objects and Names | additional | `exam-intro_python_sample_final_24_25-13-w1-objects-and-names` | +| 14 | Loops | Loops | additional | `exam-intro_python_sample_final_24_25-14-w2-loops` | +| 15 | Functions (Scope) | Conditions | additional | `exam-intro_python_sample_final_24_25-15-w2-conditions` | +| 16 | Lambdas | Higher-Order Patterns | additional | `exam-intro_python_sample_final_24_25-16-w3-higher-order-patterns` | +| 17 | Iterables/Logic | Defining and Calling Functions | additional | `exam-intro_python_sample_final_24_25-17-w3-defining-and-calling-functions` | +| 18 | Slicing | Conditions | additional | `exam-intro_python_sample_final_24_25-18-w2-conditions` | +| 19 | Dictionaries | Defining and Calling Functions | additional | `exam-intro_python_sample_final_24_25-19-w3-defining-and-calling-functions` | +| 20 | Dictionaries | Defining and Calling Functions | additional | `exam-intro_python_sample_final_24_25-20-w3-defining-and-calling-functions` | +| 21 | Dict Iteration | Defining and Calling Functions | additional | `exam-intro_python_sample_final_24_25-21-w3-defining-and-calling-functions` | +| 22 | String Methods | Conditions | additional | `exam-intro_python_sample_final_24_25-22-w2-conditions` | +| 23 | Functions (*args) | Arguments | additional | `exam-intro_python_sample_final_24_25-23-w3-arguments` | +| 24 | Modules | Conditions | additional | `exam-intro_python_sample_final_24_25-24-w2-conditions` | + +## Follow-up + +- Roadmap item: [RM-008](../../docs/specs/RM-008-exam-snippet-discoverability.md) +- Validated findings file: `tmp/exam_coverage_audit/sample_final_findings.json` diff --git a/data/quality/exam_coverage_audit_summary.md b/data/quality/exam_coverage_audit_summary.md new file mode 100644 index 0000000..2765c8c --- /dev/null +++ b/data/quality/exam_coverage_audit_summary.md @@ -0,0 +1,77 @@ +# Exam Coverage Audit Summary + +Audit date: `2026-03-22` + +## Scope + +- Method: vision-first review of rendered PNG pages only +- PDFs reviewed: 7 unique exams +- Duplicate handling: excluded the duplicate 2022 final copy +- Official scoring corpus: + - common exam questions + - key points + - key-point details + - AI examples + - recommended source snippets + - additional source snippets +- `ai_summary` was tracked as a follow-up signal only and did not materially change any audited question outcome + +## Overall Result + +- Total questions reviewed: `168` +- Score `3`: `87` +- Score `2`: `58` +- Score `1`: `22` +- Score `0`: `1` +- Questions answerable from the builder without outside knowledge (`score >= 2`): `145 / 168` (`86.3%`) + +## By Exam + +| Exam | Qs | 3 | 2 | 1 | 0 | Verdict | +|---|---:|---:|---:|---:|---:|---| +| `sample-final-plus-answers` | 24 | 24 | 0 | 0 | 0 | Excellent raw coverage; discoverability still weak because many exact matches live in `additional`. | +| `trial-final-exam-solutions-introduction-to-python-3077951` | 24 | 24 | 0 | 0 | 0 | Excellent raw coverage; exact matches already exist for every question. | +| `introduction-to-python-trial-final-exam-solutions-py22` | 24 | 7 | 12 | 5 | 0 | Strong coverage with a mix of exact and concept-level support. | +| `final-exam-study-guide-trial-python-basics-2023` | 24 | 6 | 12 | 6 | 0 | Good coverage, but several synthesis-heavy questions still need prior knowledge. | +| `final-exam-solutions-for-python-programming-62oop21` | 24 | 6 | 12 | 5 | 1 | Good coverage overall; one genuine gap remained. | +| `resit-exam-guidelines-for-intro-to-python-6013b0470y-july-2023` | 24 | 10 | 11 | 3 | 0 | Strong coverage with only a few partial-support questions. | +| `resit-solutions-for-introduction-to-python-35761538` | 24 | 10 | 11 | 3 | 0 | Strong coverage with only a few partial-support questions. | + +## Strongest Findings + +- The current-year sample final is fully covered at `24 / 24` exact matches. +- The later-course trial final is also fully covered at `24 / 24` exact matches. +- Across the full deduplicated audit set, exact-match coverage is already very high because many practice-exam questions were imported into the builder as selectable `source_exam` items. +- There was only one audited `score 0` question: the 2022 final question asking for the sub-list with the highest element sum from a list of lists. + +## Why This Is Not “Great” Yet + +- Discoverability is weaker than raw coverage. + - In the current sample final alone, `14 / 24` exact matches are only surfaced in `additional`. + - Several exact matches are routed under topic cards that are not intuitive for students. +- The weaker questions cluster around synthesis-heavy tasks rather than direct recall: + - multi-method OOP implementations + - interval-overlap / datetime logic + - some pandas construction and transformation tasks + - a few string-formatting and `kwargs` ordering questions +- Exact coverage is inflated by imported exam snippets. That is useful, but it means “the builder contains the answer somewhere” is stronger than “a student will easily find the right answer path.” + +## Practical Verdict + +The cheat sheet generator is already strong on raw exam coverage, and very strong for the current sample final. I would not call it great yet for student-facing use, because discoverability and topic routing still lag behind the underlying content quality. + +If the goal is “can the builder answer practice-exam questions at all?”, the answer is yes. + +If the goal is “can a student quickly find the right support without hunting through `additional` or oddly routed cards?”, the answer is not consistently yes yet. + +## Recommended Next Step + +- Prioritize [RM-008](../../docs/specs/RM-008-exam-snippet-discoverability.md): + - promote exact exam-match items out of `additional` when appropriate + - fix misrouted exam snippets + - keep auditing after each curation pass + +## Notes + +- The current sample-final detailed map is saved in [current_sample_exam_coverage_report.md](./current_sample_exam_coverage_report.md). +- The rendered audit packet is available under `tmp/exam_coverage_audit/`. diff --git a/data/study_db.json b/data/study_db.json index b3aadd7..4c1e8ce 100644 --- a/data/study_db.json +++ b/data/study_db.json @@ -64,9 +64,42 @@ "materials/post_midterm/practice_exams_previous_years/resit-exam-guidelines-for-intro-to-python-6013b0470y-july-2023.pdf", "materials/post_midterm/practice_exams_previous_years/resit-solutions-for-introduction-to-python-35761538.pdf", "materials/post_midterm/Sample Final plus answers.pdf", - "materials/post_midterm/practice_exams_previous_years/trial-final-exam-solutions-introduction-to-python-3077951.pdf" + "materials/post_midterm/practice_exams_previous_years/trial-final-exam-solutions-introduction-to-python-3077951.pdf", + "materials/homework/week 1/Bonus_Exercise.py", + "materials/homework/week 1/Bonus_Exercise_Solved.py", + "materials/homework/week 1/Exercise 1.py", + "materials/homework/week 1/Exercise_1.2.py", + "materials/homework/week 1/Exercise_1.3.py", + "materials/homework/week 1/Exercise_1.4.py", + "materials/homework/week 1/Exercise_1.5.py", + "materials/homework/week 1/Exercise_1.6.py", + "materials/homework/week 1/Exercise_1.7.py", + "materials/homework/week 1/Exercise_1.8.py", + "materials/homework/week 1/Exercise_1.9.py", + "materials/homework/week 1/Solutions week 1 (1).txt", + "materials/homework/week 2/Exercise_2.1.py", + "materials/homework/week 2/Exercise_2.2.py", + "materials/homework/week 2/Exercise_2.3.py", + "materials/homework/week 2/Exercise_2.4.py", + "materials/homework/week 2/Exercise_2.5.py", + "materials/homework/week 2/Exercise_2.6.py", + "materials/homework/week 2/Exercise_2.7.py", + "materials/homework/week 2/Exercise_2.8.py", + "materials/homework/week 2/Exercise_2.9.py", + "materials/homework/week 2/Solutions week 2.txt", + "materials/homework/week 3/Exercise_3.1.py", + "materials/homework/week 3/Exercise_3.2.py", + "materials/homework/week 3/Exercise_3.3.py", + "materials/homework/week 3/Exercise_3.4.py", + "materials/homework/week 3/Exercise_3.5.py", + "materials/homework/week 3/Exercise_3.6.py", + "materials/homework/week 3/Exercise_3.7.py", + "materials/homework/week 3/Exercise_3.8.py", + "materials/homework/week 3/Exercise_3.9.py", + "materials/homework/week 3/Solutions week 3.txt", + "materials/post_midterm/practice_exams_previous_years/final-exam-solutions-for-python-programming-62oop21.pdf" ], - "last_updated": "2026-03-21T21:26:18Z" + "last_updated": "2026-03-22T21:40:24Z" }, "weeks": [ { @@ -2710,7 +2743,121 @@ ], "sources": [ "materials/lectures/Lecture Week 1.md", - "materials/notebooks/Notebook Week 1.ipynb" + "materials/notebooks/Notebook Week 1.ipynb", + "materials/homework/week 1/Bonus_Exercise.py", + "materials/homework/week 1/Bonus_Exercise_Solved.py", + "materials/homework/week 1/Exercise 1.py", + "materials/homework/week 1/Exercise_1.2.py", + "materials/homework/week 1/Exercise_1.3.py", + "materials/homework/week 1/Exercise_1.4.py", + "materials/homework/week 1/Exercise_1.5.py", + "materials/homework/week 1/Exercise_1.6.py", + "materials/homework/week 1/Exercise_1.7.py", + "materials/homework/week 1/Exercise_1.8.py", + "materials/homework/week 1/Exercise_1.9.py", + "materials/homework/week 1/Solutions week 1 (1).txt" + ], + "homework_cells": [ + { + "cell_index": 1, + "week": 1, + "cell_type": "code", + "topic": "indexing", + "is_advanced_optional": false, + "source": "x = ['A','B','A','C','B','A','B']\nn = input('The index of which iteration of B would you like to find?')\ni = -1\ntry:\n for j in range(int(n)):\n i = x.index('B',i+1)\n print(i)\nexcept ValueError:\n print('There are fewer than ' + n + ' instances of B in the list.') #Either this\n print('There are only ' + str(j) + ' instances of B in the list.') #or this option is fine for error handling", + "outputs": [], + "source_origin": "materials/homework/week 1/Bonus_Exercise_Solved.py" + }, + { + "cell_index": 2, + "week": 1, + "cell_type": "code", + "topic": "arithmetic_operators", + "is_advanced_optional": false, + "source": "# source: materials/homework/week 1/Exercise 1.py\nprint(max(30 - x, 0))", + "outputs": [], + "source_origin": "materials/homework/week 1/Exercise 1.py" + }, + { + "cell_index": 3, + "week": 1, + "cell_type": "code", + "topic": "arithmetic_operators", + "is_advanced_optional": false, + "source": "# source: materials/homework/week 1/Exercise_1.2.py\nprint(round(100 * (1 + x / 100)**4, 2))", + "outputs": [], + "source_origin": "materials/homework/week 1/Exercise_1.2.py" + }, + { + "cell_index": 4, + "week": 1, + "cell_type": "code", + "topic": "arithmetic_operators", + "is_advanced_optional": false, + "source": "# source: materials/homework/week 1/Exercise_1.3.py\nprint((64 // package_size) * package_price + (64 % package_size) * individual_price)", + "outputs": [], + "source_origin": "materials/homework/week 1/Exercise_1.3.py" + }, + { + "cell_index": 5, + "week": 1, + "cell_type": "code", + "topic": "strings", + "is_advanced_optional": false, + "source": "# source: materials/homework/week 1/Exercise_1.4.py\nprint(2 * (x + '-3-') + x)", + "outputs": [], + "source_origin": "materials/homework/week 1/Exercise_1.4.py" + }, + { + "cell_index": 6, + "week": 1, + "cell_type": "code", + "topic": "boolean_operators", + "is_advanced_optional": false, + "source": "# source: materials/homework/week 1/Exercise_1.5.py\nprint('mnop' * (1 - x))", + "outputs": [], + "source_origin": "materials/homework/week 1/Exercise_1.5.py" + }, + { + "cell_index": 7, + "week": 1, + "cell_type": "code", + "topic": "type_conversion", + "is_advanced_optional": false, + "source": "# source: materials/homework/week 1/Exercise_1.6.py\nprint(float(x + '50'))", + "outputs": [], + "source_origin": "materials/homework/week 1/Exercise_1.6.py" + }, + { + "cell_index": 8, + "week": 1, + "cell_type": "code", + "topic": "indexing", + "is_advanced_optional": false, + "source": "# source: materials/homework/week 1/Exercise_1.7.py\nprint([x[3], x[0], x[2]])", + "outputs": [], + "source_origin": "materials/homework/week 1/Exercise_1.7.py" + }, + { + "cell_index": 9, + "week": 1, + "cell_type": "code", + "topic": "indexing", + "is_advanced_optional": false, + "source": "# source: materials/homework/week 1/Exercise_1.8.py\nprint([[1 - x[0][0], 1 - x[0][1]], [1 - x[1][0], 1 - x[1][1]]])", + "outputs": [], + "source_origin": "materials/homework/week 1/Exercise_1.8.py" + }, + { + "cell_index": 10, + "week": 1, + "cell_type": "code", + "topic": "slicing", + "is_advanced_optional": false, + "source": "# source: materials/homework/week 1/Exercise_1.9.py\nleft = x.index(15) + 1\nremainder_x = x[left:]\nright = left + remainder_x.index(15)\nprint(x[left:right])", + "outputs": [], + "source_origin": "materials/homework/week 1/Exercise_1.9.py" + } ] }, { @@ -5266,7 +5413,109 @@ ], "sources": [ "materials/lectures/Lecture Week 2.md", - "materials/notebooks/Notebook Week 2.ipynb" + "materials/notebooks/Notebook Week 2.ipynb", + "materials/homework/week 2/Exercise_2.1.py", + "materials/homework/week 2/Exercise_2.2.py", + "materials/homework/week 2/Exercise_2.3.py", + "materials/homework/week 2/Exercise_2.4.py", + "materials/homework/week 2/Exercise_2.5.py", + "materials/homework/week 2/Exercise_2.6.py", + "materials/homework/week 2/Exercise_2.7.py", + "materials/homework/week 2/Exercise_2.8.py", + "materials/homework/week 2/Exercise_2.9.py", + "materials/homework/week 2/Solutions week 2.txt" + ], + "homework_cells": [ + { + "cell_index": 1, + "week": 2, + "cell_type": "code", + "topic": "dictionaries", + "is_advanced_optional": false, + "source": "# source: materials/homework/week 2/Exercise_2.1.py\ny = {}\nfor var in '0123456789':\n if var in x:\n y[var]=x.count(var)\nprint(y)\n\n# Alternative Solution:\n\ny = {}\nfor element in x:\n if element in \"0123456789\":\n y[element] = x.count(element)\nprint(y)", + "outputs": [], + "source_origin": "materials/homework/week 2/Exercise_2.1.py" + }, + { + "cell_index": 2, + "week": 2, + "cell_type": "code", + "topic": "while_loops", + "is_advanced_optional": false, + "source": "# source: materials/homework/week 2/Exercise_2.2.py\nimport math\n\ny = {}\nangle = 0\nwhile angle <= 45:\n angle_in_radians = math.radians(angle)\n y[angle] = round(math.tan(angle_in_radians), 4)\n angle = angle + x", + "outputs": [], + "source_origin": "materials/homework/week 2/Exercise_2.2.py" + }, + { + "cell_index": 3, + "week": 2, + "cell_type": "code", + "topic": "dictionaries", + "is_advanced_optional": false, + "source": "# source: materials/homework/week 2/Exercise_2.3.py\ny = {'c': 3, 'd': 3}\nfor key, value in y.items():\n if key in x:\n del x[key]\n else:\n x[key] = value", + "outputs": [], + "source_origin": "materials/homework/week 2/Exercise_2.3.py" + }, + { + "cell_index": 4, + "week": 2, + "cell_type": "code", + "topic": "enumerate", + "is_advanced_optional": false, + "source": "# source: materials/homework/week 2/Exercise_2.4.py\ny = {}\nfor key, value in enumerate(x):\n y['highest' if value == max(x) else key]= value", + "outputs": [], + "source_origin": "materials/homework/week 2/Exercise_2.4.py" + }, + { + "cell_index": 5, + "week": 2, + "cell_type": "code", + "topic": "zip", + "is_advanced_optional": false, + "source": "# source: materials/homework/week 2/Exercise_2.5.py\nx = {}\nfor key, value in zip(keys, values):\n if key != value and value % 5:\n x[key] = value", + "outputs": [], + "source_origin": "materials/homework/week 2/Exercise_2.5.py" + }, + { + "cell_index": 6, + "week": 2, + "cell_type": "code", + "topic": "dictionaries", + "is_advanced_optional": false, + "source": "# source: materials/homework/week 2/Exercise_2.6.py\nsorted_keys = sorted(x.keys(), reverse=True)\n\nresult = []\nfor key in sorted_keys:\n result.append(x[key])\n\nprint(result)", + "outputs": [], + "source_origin": "materials/homework/week 2/Exercise_2.6.py" + }, + { + "cell_index": 7, + "week": 2, + "cell_type": "code", + "topic": "truthy_falsy", + "is_advanced_optional": false, + "source": "# source: materials/homework/week 2/Exercise_2.7.py\nprint(sum(x) % 2 == 0)", + "outputs": [], + "source_origin": "materials/homework/week 2/Exercise_2.7.py" + }, + { + "cell_index": 8, + "week": 2, + "cell_type": "code", + "topic": "conditions", + "is_advanced_optional": false, + "source": "# source: materials/homework/week 2/Exercise_2.8.py\nresult = []\nfor element in x:\n if element <= d:\n text = \"cat4\"\n elif element >= c:\n text = \"cat3\"\n elif element < b:\n text = \"cat2\"\n elif element > a:\n text = \"cat1\"\n else:\n text = \"catunknown\"\n result.append(text)\n\nprint(result)", + "outputs": [], + "source_origin": "materials/homework/week 2/Exercise_2.8.py" + }, + { + "cell_index": 9, + "week": 2, + "cell_type": "code", + "topic": "for_loops", + "is_advanced_optional": false, + "source": "# source: materials/homework/week 2/Exercise_2.9.py\ndemand = []\nfor buyer_values in buyers.values():\n demand = demand + buyer_values\ndemand = sorted(demand, reverse=True)\n\nsupply = []\nfor seller_values in sellers.values():\n supply = supply + seller_values\nsupply = sorted(supply, reverse=False)\n\nquantity_sold = 0\nfor buyer_value, supplyer_value in zip(demand, supply):\n quantity_sold += buyer_value >= supplyer_value\n\nprint(quantity_sold)", + "outputs": [], + "source_origin": "materials/homework/week 2/Exercise_2.9.py" + } ] }, { @@ -7962,7 +8211,109 @@ ], "sources": [ "materials/lectures/Lecture Week 3.md", - "materials/notebooks/Notebook Week 3.ipynb" + "materials/notebooks/Notebook Week 3.ipynb", + "materials/homework/week 3/Exercise_3.1.py", + "materials/homework/week 3/Exercise_3.2.py", + "materials/homework/week 3/Exercise_3.3.py", + "materials/homework/week 3/Exercise_3.4.py", + "materials/homework/week 3/Exercise_3.5.py", + "materials/homework/week 3/Exercise_3.6.py", + "materials/homework/week 3/Exercise_3.7.py", + "materials/homework/week 3/Exercise_3.8.py", + "materials/homework/week 3/Exercise_3.9.py", + "materials/homework/week 3/Solutions week 3.txt" + ], + "homework_cells": [ + { + "cell_index": 1, + "week": 3, + "cell_type": "code", + "topic": "nested_loops", + "is_advanced_optional": false, + "source": "# source: materials/homework/week 3/Exercise_3.1.py\ndef main(minimum, maximum):\n result = {}\n for first in range(minimum, maximum + 1):\n for second in range(minimum, maximum + 1):\n result[(first, second)] = first - second\n return result", + "outputs": [], + "source_origin": "materials/homework/week 3/Exercise_3.1.py" + }, + { + "cell_index": 2, + "week": 3, + "cell_type": "code", + "topic": "keyword_args", + "is_advanced_optional": false, + "source": "# source: materials/homework/week 3/Exercise_3.2.py\ndef main(**kwargs):\n x = {}\n for key, value in kwargs.items():\n x[key] = int(value % 5)\n return x", + "outputs": [], + "source_origin": "materials/homework/week 3/Exercise_3.2.py" + }, + { + "cell_index": 3, + "week": 3, + "cell_type": "code", + "topic": "args_star", + "is_advanced_optional": false, + "source": "# source: materials/homework/week 3/Exercise_3.3.py\ndef main(*args, allowed_value=16):\n x = {}\n for arg in args:\n for key, value in arg.items():\n if value == allowed_value:\n x[key] = value\n return x", + "outputs": [], + "source_origin": "materials/homework/week 3/Exercise_3.3.py" + }, + { + "cell_index": 4, + "week": 3, + "cell_type": "code", + "topic": "default_args", + "is_advanced_optional": false, + "source": "# source: materials/homework/week 3/Exercise_3.4.py\ndef main(value_list, excluded_type=int):\n x = []\n for item in value_list:\n if type(item) != excluded_type:\n x.append(item)\n return x", + "outputs": [], + "source_origin": "materials/homework/week 3/Exercise_3.4.py" + }, + { + "cell_index": 5, + "week": 3, + "cell_type": "code", + "topic": "args_star", + "is_advanced_optional": false, + "source": "# source: materials/homework/week 3/Exercise_3.5.py\ndef main(*args):\n x = {}\n for key in args:\n y = []\n for number in args:\n if number < key and key % number == 0:\n y.append(number)\n x[key] = sorted(y, reverse=True)\n return x", + "outputs": [], + "source_origin": "materials/homework/week 3/Exercise_3.5.py" + }, + { + "cell_index": 6, + "week": 3, + "cell_type": "code", + "topic": "function_factories", + "is_advanced_optional": false, + "source": "# source: materials/homework/week 3/Exercise_3.6.py\ndef main(sales_before_entry):\n def calculate_hhi(sales_volumes):\n total_sales = sum(sales_volumes)\n hhi = 0\n for volume in sales_volumes:\n hhi += round(100 * volume / total_sales)**2\n return hhi\n\n hhi_before_entry = calculate_hhi(sales_before_entry)\n hhi_after_entry = calculate_hhi(sales_before_entry + [40])\n\n return hhi_before_entry - hhi_after_entry", + "outputs": [], + "source_origin": "materials/homework/week 3/Exercise_3.6.py" + }, + { + "cell_index": 7, + "week": 3, + "cell_type": "code", + "topic": "default_args", + "is_advanced_optional": false, + "source": "# source: materials/homework/week 3/Exercise_3.7.py\ndef main(symbols, winning_symbol=\"*\"):\n pattern = 2 * (winning_symbol + \" \") + winning_symbol\n match = winning_symbol + \"-BINGO!!!\"\n no_match = \"--\"\n return match if symbols == pattern else no_match", + "outputs": [], + "source_origin": "materials/homework/week 3/Exercise_3.7.py" + }, + { + "cell_index": 8, + "week": 3, + "cell_type": "code", + "topic": "zip", + "is_advanced_optional": false, + "source": "# source: materials/homework/week 3/Exercise_3.8.py\ndef main(list_1, list_2):\n result = []\n for first, second in zip(list_1, list_2):\n result.append(None if first == second else min(first, second))\n return result", + "outputs": [], + "source_origin": "materials/homework/week 3/Exercise_3.8.py" + }, + { + "cell_index": 9, + "week": 3, + "cell_type": "code", + "topic": "lambda", + "is_advanced_optional": false, + "source": "# source: materials/homework/week 3/Exercise_3.9.py\nprint(sum(map(lambda x: 5 * x + 6, integer_list)))", + "outputs": [], + "source_origin": "materials/homework/week 3/Exercise_3.9.py" + } ] }, { @@ -17260,63 +17611,67 @@ "topic_analysis": { "topic_frequency_across_all_exams": [ [ - "OOP", - 4 + "dictionary / dict", + 11 ], [ - "dictionaries", - 3 + "id", + 10 ], [ - "Dictionaries", - 3 + "list", + 5 ], [ - "mutable / immutable", - 3 + "enumerate / loop", + 4 ], [ - "pandas", - 3 + "id / type / types", + 4 ], [ - "scope / global", - 3 + "loop", + 4 ], [ - "slicing", + "OOP", + 4 + ], + [ + "Dictionaries", 3 ], [ - "*args", - 2 + "dictionary / dict / key value", + 3 ], [ - "filter function", - 2 + "function", + 3 ], [ - "for loops / enumerate", - 2 + "id / name", + 3 ], [ - "function factories / closures", - 2 + "lambda / map", + 3 ], [ - "lambda", - 2 + "pandas", + 3 ], [ - "map function", + "condition / in", 2 ], [ - "scope / UnboundLocalError", + "in", 2 ], [ - "sorted / key", + "scope / global", 2 ], [ @@ -17331,18 +17686,6 @@ "strings", 2 ], - [ - "truthy / falsy", - 2 - ], - [ - "type conversion", - 2 - ], - [ - "*args / **kwargs", - 1 - ], [ "*args / passing to function", 1 @@ -17424,115 +17767,107 @@ 1 ], [ - "augmented operators", + "6-OOP-1", 1 ], [ - "Comprehensions", + "6-OOP-2", 1 ], [ - "conditions / conditional expression", + "6-strings-1", 1 ], [ - "conditions / truthy falsy", + "6-strings-2", 1 ], [ - "Data Types", + "7-pandas-1", 1 ], [ - "Datetime (Arithmetic)", + "argument", 1 ], [ - "Datetime (Parsing)", - 1 - ], - [ - "default args", + "argument / **kwargs / kwargs", 1 ], [ - "default args / mutable defaults", + "argument / *args", 1 ], [ - "default arguments / mutable defaults", + "argument / default", 1 ], [ - "Dict Iteration", + "Comprehensions", 1 ], [ - "dictionaries - comprehension - 3", + "Data Types", 1 ], [ - "dictionaries / average", + "Datetime (Arithmetic)", 1 ], [ - "dictionaries / indexing", + "Datetime (Parsing)", 1 ], [ - "dictionaries / nested dicts", + "Dict Iteration", 1 ], [ - "dictionaries / zip / counting", + "dictionaries - comprehension - 3", 1 ], [ - "enumerate / dictionaries / conditions", + "dictionaries / average", 1 ], [ - "for loops / range", + "dictionaries / indexing", 1 ], [ - "for vs while / loop control", + "dictionaries / nested dicts", 1 ], [ - "Functions (*args)", + "dictionaries / zip / counting", 1 ], [ - "Functions (Scope)", + "enumerate", 1 ], [ - "identity / is operator", + "enumerate / dictionaries / conditions", 1 ], [ - "indexing / negative", + "Functions (*args)", 1 ], [ - "indexing / slicing", + "Functions (Scope)", 1 ], [ "Iterables/Logic", 1 ], - [ - "keyword args / **kwargs", - 1 - ], [ "Keyword Arguments", 1 ], [ - "lambda / sorted", + "lambda", 1 ], [ @@ -17543,14 +17878,6 @@ "List Comprehensions", 1 ], - [ - "lists", - 1 - ], - [ - "lists / append vs extend", - 1 - ], [ "lists / sets / duplicates", 1 @@ -17567,44 +17894,16 @@ "Loops", 1 ], - [ - "map / filter", - 1 - ], [ "Modules", 1 ], - [ - "mutable args", - 1 - ], - [ - "mutable args / side effects", - 1 - ], - [ - "nested functions / scope", - 1 - ], - [ - "nested loops", - 1 - ], - [ - "nested loops / complexity", - 1 - ], [ "nested loops / pairs", 1 ], [ - "objects / identity", - 1 - ], - [ - "objects / types", + "none", 1 ], [ @@ -17631,34 +17930,18 @@ "Pandas (Subset/Sort)", 1 ], - [ - "positional / keyword args", - 1 - ], - [ - "reduce function", - 1 - ], - [ - "return / None", - 1 - ], [ "return / None / global", 1 ], [ - "return statement", + "scope / global / local", 1 ], [ "Scope and Functions", 1 ], - [ - "sets", - 1 - ], [ "Slicing", 1 @@ -17668,7 +17951,7 @@ 1 ], [ - "string indexing", + "type / types", 1 ], [ @@ -17679,161 +17962,71 @@ "Types and Lists", 1 ], - [ - "while loops", - 1 - ], - [ - "while loops / walrus operator", - 1 - ], [ "While Loops and String Formatting", 1 - ], - [ - "zip / looping", - 1 ] ], "most_tested_topics": [ - "OOP", - "dictionaries", - "Dictionaries", - "mutable / immutable", - "pandas" + "dictionary / dict", + "id", + "list", + "enumerate / loop", + "id / type / types" ], "topics_in_lectures_not_yet_in_exams": [ - "What is Python", - "Objects", - "Types", - "Assignment statements", - "Names", - "Arithmetic operators", - "Comparison operators", - "Boolean operators", - "Mutable vs immutable", - "Indexing", - "Range", - "Functions intro", - "Importing packages", - "Python execution model", - "Objects: core properties", - "Mutable vs immutable types", - "Assignment statements — reading right to left", - "Object types — the 8 types to know", - "Names / variable naming rules", - "range()", - "Functions — basics", - "Exam question types", - "Augmented assignment operators", + "Python Basics", + "Objects and Names", + "Operators and Truth", + "Sequences and Access", + "Functions and Imports", + "Execution Model, Logical Lines, and Comments", + "Objects, Types, Mutability, Assignment, and Names", + "Arithmetic, Comparison, and Boolean Operators", + "Indexing, Slicing, and range()", + "Built-ins Intro, Functions, and Modules", + "Dictionaries and Mappings", + "Lists and Sets", "Conditions", - "Boolean operators / precedence", - "Conditional statements", - "Conditional expressions", - "For-loops", - "While-loops", - "Walrus operator", - "Looping over dicts (keys/values/items)", - "enumerate()", - "zip()", - "Truthy and Falsy", - "Lists vs Dictionaries vs Sets — ordered/unordered", - "Conditions and boolean operators — precedence", - "Conditional statements and expressions", - "Looping over dictionaries", - "Walrus operator :=", - "Type conversion (explicit)", - "Function definitions", - "Calling functions", - "Return statements", - "Implicit return (None)", - "Multiple return values", - "Global and local names / scope", - "Positional arguments", - "**kwargs", - "Default arguments", - "Mutable argument problem", - "Mutable default problem", - "Nested functions", - "Function factories", - "Lambda functions", - "map()", - "filter()", - "reduce()", - "sorted() with key", - "pass", - "Nested for-loops", - "Function definition and calling", - "Implicit return — None", - "Single-element tuple", - "pass keyword", - "Global and local scope", - "*args — undefined number of positional arguments", - "Keyword arguments and **kwargs", - "Nested functions and function factories", - "Methods vs functions", - "String Slicing and Manipulation", - "F-strings", - "Object-Oriented Programming (OOP)", + "Conversion and Truthiness", + "Creation, Lookup, Updates, and Key Constraints", + "Sequences, Uniqueness, and Common Operations", + "Comparisons, `in`, Precedence, and Conditional Expressions", + "for, while, Dictionary Iteration, enumerate(), zip(), and Walrus", + "Explicit Conversion and Truthy/Falsy Rules", + "Defining and Calling Functions", + "Return Behavior", + "Scope", + "Arguments", + "Higher-Order Patterns", + "def, Calls, and Methods vs Functions", + "return, Implicit None, Multiple Returns, pass, and Single-Element Tuples", + "Global vs Local Names and Scope Errors", + "Positional, Keyword, Default, *args, **kwargs, and Mutable Argument Traps", + "Nested Functions, Factories, lambda, map, filter, reduce, and sorted(key=...)", + "String Fundamentals", + "String Operations and Methods", + "String Formatting", + "OOP Fundamentals", "Error Handling", - "The String Module", - "String Immutability", - "String Searching: find vs index", - "String Slicing with Step", - "The join Method", - "The replace Method", - "F-strings Basics", - "F-strings Debugging", - "F-strings Formatting", - "Class Definition and __init__", - "The self Parameter", - "Class vs Instance Attributes", - "Error Handling: try-except", - "The raise Keyword", - "Escape Characters", - "String Stripping", - "Pandas Series and DataFrames", - "Data Selection (loc, iloc, shortcuts)", - "Sorting and Statistics", - "Vectorized Operations and Broadcasting", - "String and Function Mapping", - "Combining Data (Concat, Merge, Groupby)", - "pd.Series", - "pd.DataFrame", - "Viewing Data", - "Selection: loc", - "Selection: iloc", - "Selection Result Types", - "Boolean Indexing", - "Sorting", - "Broadcasting", - "Vectorized String Methods", - "isin()", - "apply()", - "Missing Data", - "Concatenation", - "Merging", - "Grouping", - "DatetimeIndex", + "Quotes, Escape Characters, and Immutability", + "Slicing with Step, Search, replace, join, strip, and the string Module", + "f-strings Basics, Formatting, and Debug Form", + "Class Definition, __init__, self, and Attribute Basics", + "try/except and raise", + "Pandas Core Structures", + "Inspecting and Selecting Data", + "Working With Values", + "Combining Data", + "Series, DataFrame, and Creation Patterns", + "head, tail, describe, loc, iloc, Result Types, and Boolean Indexing", + "Sorting, Missing Data, Broadcasting, Vectorized Strings, isin, map, and apply", + "Concatenation, Merging, and Grouping", "Generators and Iterators", - "Date and Time Handling", - "State Management", - "Set Comprehensions", - "String Transformations via List Comprehension", - "Nested Dictionary Comprehensions", - "Walrus Operator in Comprehensions", - "Map and Filter vs. Comprehensions", - "Generator Functions", - "Generator Comprehensions", - "Iterators", - "datetime.now and Timestamps", - "strftime: Date to String", - "strptime: String to Date", - "Timedelta and Date Arithmetic", - "The replace() Method", - "Dictionary Comprehensions with Logic", - "Enumerate in Comprehensions" + "Datetime", + "List/Dict/Set Comprehensions, Nested Variants, Logic Filters, Walrus, and enumerate Patterns", + "Iterator Protocol, Generator Functions, and Generator Comprehensions", + "now, Timestamps, strftime, strptime, timedelta, and Date Arithmetic" ], "exam_question_counts": { "trial_midterm": 24, @@ -17847,7 +18040,7 @@ "Resit 22/23": 7, "intro_python_sample_final_24_25": 24, "Trial final exam Introduction to Python": 6, - "total": 142 + "total": 137 } } } diff --git a/docs/ROADMAP.md b/docs/ROADMAP.md index 4929532..93a365e 100644 --- a/docs/ROADMAP.md +++ b/docs/ROADMAP.md @@ -23,6 +23,7 @@ Current implementation handoff: | RM-005 | Medium | planned | Codebase hygiene | Reduce >300-line files to improve readability and maintenance velocity. | [Template](./specs/SPEC_TEMPLATE.md) | | RM-006 | Medium | planned | Topic Explorer UX | Continue densifying the Topic Explorer sidebar and source rails so long weeks remain fast to scan without layout bloat. | [Template](./specs/SPEC_TEMPLATE.md) | | RM-007 | Medium | planned | Topic curation | Merge the densest remaining topic clusters inside the new course-outline buckets without losing evidence quality. | [RM-007](./specs/RM-007-course-outline-topic-merging.md) | +| RM-008 | High | in_progress | Exam discoverability | Surface exact exam-match snippets in the right topic rails, reduce critical reliance on `additional`, and evaluate making high-value `ai_summary` content selectable. | [RM-008](./specs/RM-008-exam-snippet-discoverability.md) | ## Triage Rules diff --git a/docs/TESTING.md b/docs/TESTING.md index 42c147c..9b85a5a 100644 --- a/docs/TESTING.md +++ b/docs/TESTING.md @@ -30,8 +30,28 @@ make gemini-benchmark make gemini-prompt-experiments make gemini-health make quality-dashboard +python3 scripts/exam_coverage_audit.py prepare +python3 scripts/exam_coverage_audit.py summary ``` +## Exam Coverage Audit Prep + +```bash +python3 scripts/exam_coverage_audit.py prepare +``` + +This prepares the vision-first audit packet under: + +- `tmp/exam_coverage_audit/manifest.json` +- `tmp/exam_coverage_audit/selectable_items.json` +- `tmp/exam_coverage_audit/pages//page-XX.png` + +Notes: + +- The helper renders the unique exam PDFs only; the duplicate 2022 final is excluded from the packet. +- It mirrors the current UI's selectable-item rules, so `ai_summary` is excluded while key-point details and both source buckets are included. +- It is intended for manual or agent-led vision review of the rendered PNG pages, not text-layer parsing or OCR. + ## Maintenance Audit ```bash diff --git a/docs/curation/TOPIC_MERGING_GUIDELINES.md b/docs/curation/TOPIC_MERGING_GUIDELINES.md index 9b3710e..578e419 100644 --- a/docs/curation/TOPIC_MERGING_GUIDELINES.md +++ b/docs/curation/TOPIC_MERGING_GUIDELINES.md @@ -101,7 +101,7 @@ When merging cards manually, curate each section intentionally: - keep `related_topics` meaningful and deduped. - dedupe trap patterns by `(pattern, trap)` content. -#### `sections.lecture_snippets`, `sections.exam_questions`, `sections.notebook_snippets` +#### `sections.lecture_snippets`, `sections.exam_questions`, `sections.notebook_snippets`, `sections.homework_snippets` - union by content/ID and dedupe. - remove low-value snippets (headers, fluff, repetitive tiny notes). @@ -137,6 +137,12 @@ When merging cards manually, curate each section intentionally: - must reference IDs that exist in the card’s own source snippet buckets. - prioritize exam snippets first, then lecture, then notebook. +- include homework IDs when homework snippets are strong and exam-relevant. + +#### `sections.homework_recommended_ids` + +- must reference IDs in the card’s own `sections.homework_snippets`. +- use it to split Homework into recommended vs additional selection buckets. ### 6) Recompute/Repair Metadata @@ -177,20 +183,28 @@ print("duplicate-normalized-topics:", len(dups)) for card in cards: s = card["sections"] - for key in ["lecture_snippets", "exam_questions", "notebook_snippets", "ai_examples", "key_points_to_remember", "recommended_ids"]: + for key in ["lecture_snippets", "exam_questions", "notebook_snippets", "homework_snippets", "homework_recommended_ids", "ai_examples", "key_points_to_remember", "recommended_ids"]: assert isinstance(s.get(key), list), f'{card["id"]}: {key} must be list' assert isinstance(s.get("ai_summary"), dict), f'{card["id"]}: ai_summary must be object' assert isinstance(s.get("ai_common_questions"), dict), f'{card["id"]}: ai_common_questions must be object' valid_ids = { item.get("id") - for bucket in ["lecture_snippets", "exam_questions", "notebook_snippets"] + for bucket in ["lecture_snippets", "exam_questions", "notebook_snippets", "homework_snippets"] for item in s.get(bucket, []) if isinstance(item, dict) } for rid in s.get("recommended_ids", []): assert rid in valid_ids, f'{card["id"]}: recommended id not found: {rid}' + homework_ids = { + item.get("id") + for item in s.get("homework_snippets", []) + if isinstance(item, dict) + } + for rid in s.get("homework_recommended_ids", []): + assert rid in homework_ids, f'{card["id"]}: homework recommended id not found: {rid}' + print("integrity checks passed") PY ``` diff --git a/docs/specs/RM-008-exam-snippet-discoverability.md b/docs/specs/RM-008-exam-snippet-discoverability.md new file mode 100644 index 0000000..88f766a --- /dev/null +++ b/docs/specs/RM-008-exam-snippet-discoverability.md @@ -0,0 +1,67 @@ +# Spec: RM-008 Exam Snippet Discoverability + +## Metadata + +- ID: `RM-008` +- Status: `in_progress` +- Priority: `High` +- Owner: `codex/human` +- Last Updated: `2026-03-22` + +## Problem + +The exam coverage audit shows that the current builder can already contain exact matches for exam questions, but discoverability is weaker than coverage. In the current sample-final audit, many exact question matches are surfaced only in `additional`, and several imported exam items appear routed under topic cards that do not match the question's actual subject area. + +## Goals + +- Promote exact exam-match items so students can find them quickly without digging through `additional`. +- Repair topic/card routing for imported exam snippets whose current card placement is misleading. +- Evaluate whether a constrained subset of `ai_summary` content should become selectable when it materially improves exam answerability. + +## Non-Goals + +- Rebuild the whole card-generation pipeline in one pass. +- Make every `ai_summary` block selectable by default. + +## Proposed Solution + +Start with the current-year sample final and other audit-backed high-value exams. For each exact exam-match snippet, verify whether it sits in the correct topic card and whether it belongs in `recommended` instead of `additional`. Where exact matches are absent but `ai_summary` clearly fills a repeated gap, define a small policy for promoting only the highest-value `ai_summary` fragments into selectable content. + +## Implementation Plan + +1. Use the audit report to list exact exam-match items by question number, card topic, and `recommended`/`additional` bucket. +2. Re-route misclassified exam snippets to the correct topic cards and update `recommended_ids` so exact matches surface earlier. +3. Identify repeated cases where non-selectable `ai_summary` text materially improves answerability and draft a narrow promotion policy. +4. Re-run the exam coverage audit after each curation batch to confirm that discoverability improves, not just raw coverage. + +## Risks and Mitigations + +- Risk: Aggressively promoting items into `recommended` may make rails noisy. +- Mitigation: Limit promotion to exact matches and repeat offenders from the audit. +- Risk: Re-routing snippets may break subtopic balance or `recommended_ids`. +- Mitigation: Run integrity tests and audit validation after each curation pass. +- Risk: Making `ai_summary` selectable could bloat cards with generic text. +- Mitigation: Gate any promotion behind a strict “material exam value” rule. + +## Test Plan + +- Run `python3 scripts/exam_coverage_audit.py prepare` and revalidate findings against the updated corpus. +- Run `make leave-better`. +- Spot-check audited questions in the Topic Explorer to confirm the surfaced topic/bucket now makes sense to a student. + +## Rollout and Validation + +- First target: current-year sample final exact matches. +- 2026-03-22 curation pass: + - Re-routed the audited misclassified current sample-final exact matches into the more intuitive destination cards. + - Promoted audited exact matches from the current sample final, 2024 trial final, resits, and related high-value exams into `recommended_ids`. + - Added small selectable gap-fill examples for repeated weak themes without making `ai_summary` selectable. +- Success criteria: + - Fewer exact exam matches hidden in `additional`. + - No obviously misrouted exam snippets in audited high-value questions. + - Any newly selectable `ai_summary` content is deliberate, sparse, and clearly useful. + +## Open Questions + +- Should “exact match to a current-year or recent practice-exam question” automatically outrank generic recommended snippets? +- Should `ai_summary` promotion happen as manual curation only, or should the pipeline support a dedicated selectable-summary field? diff --git a/index.html b/index.html index 4247c76..6345dfe 100644 --- a/index.html +++ b/index.html @@ -86,7 +86,7 @@

Python Exam Cheat Sheet Builder

target="_blank" rel="noopener noreferrer" > - Buy Me a Coffee + Support the Builder @@ -304,22 +304,22 @@

Edit content

aria-describedby="supportPromptText" >
-

One Last Thing

-

If this helped you study faster, buy me a coffee for the next updates.

+

Built by one student. Shared with you for free.

- A small coffee keeps this cheat-sheet generator free and actively maintained. + This cheat-sheet generator took a lot of solo time, effort, and paid AI/tooling costs to build. If it saved you time or stress, please consider buying me a coffee as a thank-you.

-

A one-coffee thank-you makes a real difference and only takes a few seconds.

+

If this project gave you something useful for free, a small coffee is a simple way to give something back.

- +
diff --git a/materials/homework/week 1/Bonus_Exercise.py b/materials/homework/week 1/Bonus_Exercise.py new file mode 100644 index 0000000..146c7fc --- /dev/null +++ b/materials/homework/week 1/Bonus_Exercise.py @@ -0,0 +1,7 @@ +""" +Suppose you are given a list x = ['A','B','A','C','B','A','B']. Write +a programme that allows the user to find the index of the n-th instance +of 'B' in the list, where 'n' is input by the user of the programme. +Make sure to tackle the case where the user asks for something that +doesn't exist. +""" diff --git a/materials/homework/week 1/Bonus_Exercise_Solved.py b/materials/homework/week 1/Bonus_Exercise_Solved.py new file mode 100644 index 0000000..ea7d289 --- /dev/null +++ b/materials/homework/week 1/Bonus_Exercise_Solved.py @@ -0,0 +1,17 @@ +""" +Suppose you are given a list x = ['A','B','A','C','B','A','B']. Write +a programme that allows the user to find the index of the n-th instance +of 'B' in the list, where 'n' is input by the user of the programme. +Make sure to tackle the case where the user asks for something that +doesn't exist. +""" +x = ['A','B','A','C','B','A','B'] +n = input('The index of which iteration of B would you like to find?') +i = -1 +try: + for j in range(int(n)): + i = x.index('B',i+1) + print(i) +except ValueError: + print('There are fewer than ' + n + ' instances of B in the list.') #Either this + print('There are only ' + str(j) + ' instances of B in the list.') #or this option is fine for error handling \ No newline at end of file diff --git a/materials/homework/week 1/Exercise 1.py b/materials/homework/week 1/Exercise 1.py new file mode 100644 index 0000000..e9e431a --- /dev/null +++ b/materials/homework/week 1/Exercise 1.py @@ -0,0 +1,14 @@ +""" +Assume that you already have a variable called 'x', which contains an integer +value indicating the price of a company's stock. + +Suppose that you have a put option on the stock with a strike price of 30. + +The put option is just about to expire. Print its value. +As you won't exercise an option if that would lead to a loss, +the minimum value of an option is 0. + +For example: +If x = 25, then your program should print: +5 +""" diff --git a/materials/homework/week 1/Exercise_1.2.py b/materials/homework/week 1/Exercise_1.2.py new file mode 100644 index 0000000..73f5943 --- /dev/null +++ b/materials/homework/week 1/Exercise_1.2.py @@ -0,0 +1,21 @@ +""" +Assume that you already have a variable called 'x', which contains the +percentage annual interest rate paid by a bank account as a nonnegative +integer value. + +Suppose that the balance of the bank account is now 100. + +Print out what the balance of the bank account will be in 4 years. + +Before you print the new balance, use the round function to round it +to 2 digits. + +For example: if x = 20, your program should print: +207.36 +""" + +# Hint 1: how do you calculate the balance 1 year from now? + +# Hint 2: how about the balance 2 years from now? And 4 years from now? + +# Hint 3: just one more thing left: printing the result to the screen. diff --git a/materials/homework/week 1/Exercise_1.3.py b/materials/homework/week 1/Exercise_1.3.py new file mode 100644 index 0000000..0385718 --- /dev/null +++ b/materials/homework/week 1/Exercise_1.3.py @@ -0,0 +1,30 @@ +""" +Imagine that you are writing cashier software for Albert Heijn. The cashiers +scan items one-by-one, and you have to take into account package discounts +automatically (e.g. "Get 4 for the price of 3!") + +Assume that you already have a variable called 'package_price', another +variable called 'individual_price' and a variable called 'package_size' +indicating how many items a package contains. + +You can assume that it is always cheaper to buy as many packages as possible +to fill the order. Also, prices are integers. + +Print the total amount to be paid when a customer buys 64 items. + +Make sure that the printed total amount is also an integer. + +For example: +If package_price is 20, individual_price is 5, and package_size is also 5, +then your program should print: +260 +""" + +# Hint 1: how many full packages fit into 64 items if the number of +# items in a package equals the value of the variable 'package_size'? +# Have a look at the integer division operator! + + +# Hint 2: how many items are left, once you've fit as many as possible into +# packages? +# Have a look at the division remainder operator! diff --git a/materials/homework/week 1/Exercise_1.4.py b/materials/homework/week 1/Exercise_1.4.py new file mode 100644 index 0000000..891894b --- /dev/null +++ b/materials/homework/week 1/Exercise_1.4.py @@ -0,0 +1,19 @@ +""" +Assume that you already have a variable called 'x' that contains a string +value. + +Print a string that equals 3 times the value in 'x', where every +occurence of the value of 'x' is separated by the string '-3-'. + +For example: +If x = 'abc', your program should print: +abc-3-abc-3-abc +""" + +# Hint 1: how do you concatenate (= join together) two strings? + +# Hint 2: what happens when you use the multiplication operator between an +# integer and a string? + +# Hint 3: so then what combination of the two things above gives you what you +# need? diff --git a/materials/homework/week 1/Exercise_1.5.py b/materials/homework/week 1/Exercise_1.5.py new file mode 100644 index 0000000..b2b9540 --- /dev/null +++ b/materials/homework/week 1/Exercise_1.5.py @@ -0,0 +1,18 @@ +""" +Assume that you already have a variable called 'x' that contains a boolean +value. + +Print a string mnop if 'x' is False and an empty string if 'x' is True. +Try doing it without using the if statement. + +For example: +If x = False, your program should print: +mnop +""" + +# Hint 1: what integer values are True and False associated with? + +# Hint 2: how could you swap those integer values with a mathematical operation + +# Hint 3: can you think of any operations between an integer and a string +# that could be useful here? diff --git a/materials/homework/week 1/Exercise_1.6.py b/materials/homework/week 1/Exercise_1.6.py new file mode 100644 index 0000000..dcc9830 --- /dev/null +++ b/materials/homework/week 1/Exercise_1.6.py @@ -0,0 +1,15 @@ +""" +Assume that you already have a variable called 'x', which contains a string +value that represents an integer number. + +Print out a float representation of the number that you get when you write +'50' at the end of the value in 'x'. + +For example: +If x = '2', your program should print: +250.0 +""" + +# Hint 1: think about string concatenation first. + +# Hint 2: how do you convert a string to a float? diff --git a/materials/homework/week 1/Exercise_1.7.py b/materials/homework/week 1/Exercise_1.7.py new file mode 100644 index 0000000..f72adee --- /dev/null +++ b/materials/homework/week 1/Exercise_1.7.py @@ -0,0 +1,14 @@ +""" +Assume that you already have one variable called 'x', which is a list +that contains 4 elements. + +Print a new list that contains elements of x in this order: +fourth- first - third. + +If x = ['r', 'q', 'u', 'x'], then your program should print: +['x', 'r', 'u'] +""" + +# Hint 1: this one is all about list indexing. + +# Hint 2: ... and about creating a list, of course. diff --git a/materials/homework/week 1/Exercise_1.8.py b/materials/homework/week 1/Exercise_1.8.py new file mode 100644 index 0000000..f9d3ff2 --- /dev/null +++ b/materials/homework/week 1/Exercise_1.8.py @@ -0,0 +1,13 @@ +""" +Assume that you already have a variable called 'x', which contains +a list with two elements. Each element is a further list with two elements: +either 0 or 1. + +Print a list that has the same structure as x, but all the 0's should be changed into 1's and all 1's into 0's. + +For example: +If x = [[1, 1], [1, 0]], then your program should print: +[[0, 0], [0, 1]] +""" + +# Hint 1: did you know that 1 - 0 = 1 and 1 - 1 = 0? diff --git a/materials/homework/week 1/Exercise_1.9.py b/materials/homework/week 1/Exercise_1.9.py new file mode 100644 index 0000000..e0673a5 --- /dev/null +++ b/materials/homework/week 1/Exercise_1.9.py @@ -0,0 +1,17 @@ +""" +Assume that you already have one variable called 'x', which is a list that +contains at least 8 integer elements. Two elements of this list have the value +15. + +Print a list with all the elements between the two 15's. +Both 15's should not be included. You can assume that +there will only be two 15's in the list. + +For example: +If x = [21, 15, 29, 20, 15, 21, 38, 26], your program should print: +[29, 20] +""" + +# Hint 1: find the positions of both 15's first. + +# Hint 2: then think about list slicing. diff --git a/materials/homework/week 1/Solutions week 1 (1).txt b/materials/homework/week 1/Solutions week 1 (1).txt new file mode 100644 index 0000000..4b06eb5 --- /dev/null +++ b/materials/homework/week 1/Solutions week 1 (1).txt @@ -0,0 +1,51 @@ +Solutions week 1: + +The below are suggested solutions; there are typically many ways to implement ideas in code. + +========================================================================== + +Exercise 1: +print(max(30 - x, 0)) + +========================================================================== + +Exercise 2: +print(round(100 * (1 + x / 100)**4, 2)) + +========================================================================== + +Exercise 3: +print((64 // package_size) * package_price + (64 % package_size) * individual_price) + +========================================================================== + +Exercise 4: +print(2 * (x + '-3-') + x) + +========================================================================== + +Exercise 5: +print('mnop' * (1 - x)) + +========================================================================== + +Exercise 6: +print(float(x + '50')) + +========================================================================== + +Exercise 7: +print([x[3], x[0], x[2]]) + +========================================================================== + +Exercise 8: +print([[1 - x[0][0], 1 - x[0][1]], [1 - x[1][0], 1 - x[1][1]]]) + +========================================================================== + +Exercise 9: +left = x.index(15) + 1 +remainder_x = x[left:] +right = left + remainder_x.index(15) +print(x[left:right]) \ No newline at end of file diff --git a/materials/homework/week 2/Exercise_2.1.py b/materials/homework/week 2/Exercise_2.1.py new file mode 100644 index 0000000..26cf2f2 --- /dev/null +++ b/materials/homework/week 2/Exercise_2.1.py @@ -0,0 +1,31 @@ +""" +Assume that you already have a variable called 'x', which contains a list. +The elements of the list are strings consisting of a single letter or a +single digit. The list may contain duplicate elements. + +Create a new variable 'y', which is a dictionary with each of the +digits as keys and the frequency of each of those digits +as corresponding values. + +For example: +If x = ['1', 'a', 'X', '2', 'b', 'Y', '1', 'a', 'X', '1', 'a', 'X'], +then the value of y should be equal to: +{'1': 3, '2': 1} +""" + +# Hint 1: Let's just create an empty dictionary first, we'll fill it up later. +# Don't forget that it has to be named 'y'. + +# Hint 2: It seems like a good idea to examine the elements of the list +# one-by-one! + +# Hint 3: But how do we decide if a one-character string is one of the many +# possible digits? This one is tricky! + +# Hint 4: How do we count how many times an element occurs in a list? There +# must be a list method for this somewhere... + +# Hint 5: Okay, now all that is left is to add the requested key-value pair +# to the 'y' dictionary. It doesn't even matter if we do it several times, +# since that just updates an already existing key-value pair with the same +# thing. diff --git a/materials/homework/week 2/Exercise_2.2.py b/materials/homework/week 2/Exercise_2.2.py new file mode 100644 index 0000000..9c8fbb2 --- /dev/null +++ b/materials/homework/week 2/Exercise_2.2.py @@ -0,0 +1,37 @@ +""" +Assume that you already have a variable called 'x', which contains an integer. + +Create a new dictionary and call it 'y'. Its keys should be integers indicating +angles, measured in degrees, from 0 to 45 with a step size of 'x'. + +The values should equal the tangent of the corresponding keys, rounded to 4 +decimal digits. + +Import the math package to calculate the tangent of a number. + +For example: +If x = 5, then the value of y should be equal to: +{0: 0.0, 5: 0.0875, 10: 0.1763, 15: 0.2679, 20: 0.364, 25: 0.4663, 30: 0.5774, 35: 0.7002, 40: 0.8391, 45: 1.0} +""" + +# Hint 1: I think we should start by importing the math package. Seems doable. + +# Hint 2: Next step: create an empty dictionary called 'y'. Still doable. + +# Hint 3: How about a variable for the angles? Let's call it something and +# give it a value of 0 to start with. + +# Hint 4: Angles going "from 0 to 45 with a step size of 'x'", where 'x' is +# some other variable whose value we don't know??? This calls for a loop! It +# is probably a good idea to try a while loop here. (And someone please remind +# me to make it not infinite!) + +# Hint 5: Hmm, tangent, tangent, ..., isn't there a function for that in the +# math package? Where else would it be? Let's google "python math package"! + +# Hint 6: But wait, the function we've found takes angles in radians, while we +# have them in degrees. I bet there must be a function in that package that +# turns degrees into radians! + +# Hint 7: Are we done? Can we now append the key-value pair to 'y'? No? +# Oh, yeah, the rounding! At least that one is doable... diff --git a/materials/homework/week 2/Exercise_2.3.py b/materials/homework/week 2/Exercise_2.3.py new file mode 100644 index 0000000..94bdcd4 --- /dev/null +++ b/materials/homework/week 2/Exercise_2.3.py @@ -0,0 +1,22 @@ +""" +Assume that you already have a variable called 'x', which contains a dictionary. + +Modify 'x' with the dictionary y = {'c': 3, 'd': 3} in the following way: +- add to 'x' all key-value pairs of 'y' for which the key is not also present +in 'x' +- delete from 'x' all key-value pairs for which the key is also present in 'y' + +For example: +If x = {'a': 1, 'b': 2, 'c': 3}, then the value of x at the end of your program +should be equal to: +{'a': 1, 'b': 2, 'd': 3} +""" + +# Hint 1: Looping through the key-value pairs of 'y' seems like a good place +# to start. + +# Hint 2: How do we check whether a key is in a dictionary? IN a dictionary... + +# Hint 3: Key not there? Let's add the key-value pair to 'x'! + +# Hint 4: Key there? Let's delete the key-value pair from 'x'! diff --git a/materials/homework/week 2/Exercise_2.4.py b/materials/homework/week 2/Exercise_2.4.py new file mode 100644 index 0000000..b596ed6 --- /dev/null +++ b/materials/homework/week 2/Exercise_2.4.py @@ -0,0 +1,26 @@ +""" +Assume that there is already a variable 'x', which refers to a list with at +least 5, but maybe more, different integers. + +Create a dictionary called 'y', in which the keys are the indexes from the list +and the values are the values from the list, with one exception: for the +highest value in the dictionary, the key should be "highest". + +For example: +If x = [65, 43, 1, 0, 59, 16, 86, 40, 60] then the value of y should be: +{0: 65, 1: 43, 2: 1, 3: 0, 4: 59, 5: 16, 'highest': 86, 7: 40, 8: 60} +""" + +# Hint 1: Let's start by creating an empty dictionary called 'y'. + +# Hint 2: I think we have to loop through the list elements. But it would also +# be very handy to have their indices with them in the loop. This sounds so +# contrived that they must have talked about how to do it in the lecture. + +# Hint 3: Okay, I have the index, I have the element, let's just make a +# key-value pair out of them and add it to 'y'. But wait! I'd better check +# first whether the element I have is the highest one in the list. + +# Hint 4: How do I find the highest number in a list? Could sorting help? + +# Hint 5: OK, now I know what to add to 'y'. Let's get it over with! diff --git a/materials/homework/week 2/Exercise_2.5.py b/materials/homework/week 2/Exercise_2.5.py new file mode 100644 index 0000000..5101e6d --- /dev/null +++ b/materials/homework/week 2/Exercise_2.5.py @@ -0,0 +1,37 @@ +""" +Assume that you already have two variables, which are two lists: +one called 'keys', the other called 'values'. The lists have the +same length. Both lists consists of integers. The 'keys' list contains +only unique numbers. + +Create a dictionary 'x', for which all the keys are taken from the 'keys' list +and all the values from the 'values' list. Pairs are formed from +elements with the same index in their lists. The only exceptions are +when the values are divisible by 5, or when the key and the value +are equal to each other. In those cases, the key-value pair is ignored. + +For example: +If keys = [3, 2, 1, 4] and values = [3, 37, 60, 79] then the value of x should +be equal to: +{2: 37, 4: 79} +""" + +# Hint 1: Why not start by creating an empty dictionary called 'x'? + +# Hint 2: There is clearly some looping to be done here. Since we have to work +# with two lists of the same length and corresponding elements, but can only +# loop through one list at a time, it would be handy to have the indices of +# the elements of the looped list with us, too. That way, we could access the +# corresponding elements in the other list. + +# Hint 3: which of the two lists should we choose for the looping? In the grand +# scheme of things, it doesn't matter, since we can access the elements of both +# with the index. But there is an extra check to be done on the values, so +# maybe that one is more convenient to use for looping. + +# Hint 4: How to check whether a number is divisible by 5? Well, this one +# shouldn't be difficult! And don't forget to check whether the key elements +# are equal to the value elements! And don't forget about the "or" part, either! + +# Hint 5: All right, now all that's left is to add the key-value pair to 'x'. +# Given that they satisfy the two conditions above, of course. diff --git a/materials/homework/week 2/Exercise_2.6.py b/materials/homework/week 2/Exercise_2.6.py new file mode 100644 index 0000000..b7991f9 --- /dev/null +++ b/materials/homework/week 2/Exercise_2.6.py @@ -0,0 +1,22 @@ +""" +Assume that you already have a variable called 'x', which is a dictionary. + +Print a list of the values of the dictionary, sorted in descending order +of the corresponding dictionary keys. + +For example: +If x = {1: 3, 3: 4, 2: 5} your program should print: +[4, 5, 3] +""" + +# Hint 1: It never hurts to start with an empty list. Pick a name for it that +# you like. But not 'list'! That would have unpredictable consequences for the +# universe... + +# Hint 2: Check out the 'sorted' function. It takes a collection of values and +# returns them as elements in a sorted list. + +# Hint 3: Okay, now how do we build a list of dictionary values in the order +# of the sorted keys? One-by-one (for now). Think about looping! + +# Hint 4: And don't forget to print out the result, of course. diff --git a/materials/homework/week 2/Exercise_2.7.py b/materials/homework/week 2/Exercise_2.7.py new file mode 100644 index 0000000..cbb6975 --- /dev/null +++ b/materials/homework/week 2/Exercise_2.7.py @@ -0,0 +1,29 @@ +""" +Assume that you already have a variable called 'x', which is a list containing +boolean values. + +In this question, you are asked to carry out an operation on a list that +is not implemented in Python by default, so you have to program it yourself. + +The name of the operator is XOR, which, when applied to a list of booleans, +evaluates to True exactly when there is an even number of True values +in the list. + +Print the result of applying XOR to 'x'. + +For example: +If x = [True, False], then your program should print: +False +""" + +# Hint 1: Have you ever wondered about what happens when you try to add boolean +# values to each other? And how that relates to counting the number of True +# values? + +# Hint 2: There is a Python function that sums the elements of a collection. +# It has a pretty predictable name, too. Try to search for it online if +# guessing proves too hard. + +# Hint 3: How do we decide if a number is even or odd? + +# Hint 4: Don't forget about the printing. diff --git a/materials/homework/week 2/Exercise_2.8.py b/materials/homework/week 2/Exercise_2.8.py new file mode 100644 index 0000000..c1e5c4b --- /dev/null +++ b/materials/homework/week 2/Exercise_2.8.py @@ -0,0 +1,35 @@ +""" +Assume that you already have a variable called 'x', which is a list +containing integer values. Furthermore, you have 4 variables called +'a', 'b', 'c', 'd'. All of them contain an integer. + +Print a list containing strings that describe the elements of 'x' as follows: +If the element is greater than the value of 'a', use "cat1". +If the element is less than the value of 'b', use "cat2". +If the element is greater than or equal to the value of 'c', use "cat3". +If the element is less than or equal to the value of 'd', use "cat4". + +If the element fits into more than one category, use the highest category. +So, for example, if both "cat3" and "cat4" apply, use "cat4". + +If the integer doesn't fall into any of the 4 categories, use "catunknown". + +For example: +If x = [5, 10, 15, 20], a = 4, b = 9, c = 13, and d = 15 +then your program should print: +['cat4', 'cat4', 'cat4', 'cat3'] +""" + +# Hint 1: This exercise seems complex, but isn't really. Let's take it slow, +# and create an empty list first. We can call it 'cats'. + +# Hint 2: We clearly have to loop through 'x' and examine each of its elements. +# So let's create a loop for that. + +# Hint 3: Higher-numbered categories dominate lower numbered ones when both +# apply, so let's check higher-numbered categories first, and then work our way +# down with a bunch of 'if - elif - else' statements. The 'else' part is for +# the unknown category, of course. + +# Hint 4: Add the category names to 'cats' (while still inside the loop), +# and print the resulting list at the very end. diff --git a/materials/homework/week 2/Exercise_2.9.py b/materials/homework/week 2/Exercise_2.9.py new file mode 100644 index 0000000..16baf2b --- /dev/null +++ b/materials/homework/week 2/Exercise_2.9.py @@ -0,0 +1,46 @@ +""" +Assume that there are 2 dictionaries, called 'buyers' and 'sellers'. Both have +4 key-value pairs. Each value is a list with 5 integers. + +The values in the 'buyers' dictionary are the prices that each of the 4 buyers +is willing to pay for the first, second, ... unit of a product in a market. + +The values in the 'sellers' dictionary are the prices for which each of the +4 sellers is willing to sell the first, second, ... unit of the product in the +market. + +The product is homogeneous. If a seller's asking price is the same as a buyer's +offer price, the buyer buys the item. + +Print the integer value that indicates the number of items traded once all +(welfare-increasing) transactions have taken place. (That is: how many items +would be sold in an efficiently operating marketplace?) + +For example: +If buyers = {'buyer1': [24, 16, 13, 6, 5], 'buyer2': [23, 21, 19, 10, 7], 'buyer3': [21, 20, 15, 13, 10], 'buyer4': [20, 17, 9, 6, 5]}, +and sellers = {'seller1': [8, 10, 14, 19, 21], 'seller2': [6, 13, 16, 21, 23], 'seller3': [8, 12, 13, 22, 23], 'seller4': [8, 9, 13, 21, 24]}, +your program should print: +10 +""" + +# WARNING: THIS EXERCISE MAY BE CHALLENGING, BUT IS ULTIMATELY WORTH IT! + +# Hint 1: This sounds like a standard microeconomics question, maybe from an +# exam you've once taken. We have individual demand and supply functions and +# want to find the equilibrium quantity in the market. How do we do that? +# Well, as in basic micro: create aggregate demand and supply functions, and +# find where they intersect! + +# Hint 2: Let's get all the buyer prices from the 'buyers' dictionary into a +# single list (let's call it 'demand'), which we then sort from high to low. + +# Hint 3: Let's get all the seller prices from the 'sellers' dictionary into a +# single list (let's call it 'supply'), which we then sort from low to high. + +# Hint 4: Let us now loop through 'demand' (and its index) and count how many +# times the buyer price is at least as large as the corresponding seller +# price in the 'supply' list. You can, for example, set an integer variable +# called 'quantity_sold' to 0 before the looping, and then just increment it +# by 1 whenever the buyer "buys" the item from the corresponding seller. + +# Hint 5: Don't forget to print the result. diff --git a/materials/homework/week 2/Solutions week 2.txt b/materials/homework/week 2/Solutions week 2.txt new file mode 100644 index 0000000..1a99bdb --- /dev/null +++ b/materials/homework/week 2/Solutions week 2.txt @@ -0,0 +1,120 @@ +Solutions week 2: + +The below are suggested solutions; there are typically many ways to implement ideas in code. + +========================================================================== + +Exercise 1: + +y = {} +for var in '0123456789': + if var in x: + y[var]=x.count(var) +print(y) + +# Alternative Solution: + +y = {} +for element in x: + if element in "0123456789": + y[element] = x.count(element) +print(y) + +========================================================================== + +Exercise 2: + +import math + +y = {} +angle = 0 +while angle <= 45: + angle_in_radians = math.radians(angle) + y[angle] = round(math.tan(angle_in_radians), 4) + angle = angle + x + +========================================================================== + +Exercise 3: + +y = {'c': 3, 'd': 3} +for key, value in y.items(): + if key in x: + del x[key] + else: + x[key] = value + +========================================================================== + +Exercise 4: + +y = {} +for key, value in enumerate(x): + y['highest' if value == max(x) else key]= value + +========================================================================== + +Exercise 5: + +x = {} +for key, value in zip(keys, values): + if key != value and value % 5: + x[key] = value + +========================================================================== + +Exercise 6: + +sorted_keys = sorted(x.keys(), reverse=True) + +result = [] +for key in sorted_keys: + result.append(x[key]) + +print(result) + +========================================================================== + +Exercise 7: + +print(sum(x) % 2 == 0) + +========================================================================== + +Exercise 8: + +result = [] +for element in x: + if element <= d: + text = "cat4" + elif element >= c: + text = "cat3" + elif element < b: + text = "cat2" + elif element > a: + text = "cat1" + else: + text = "catunknown" + result.append(text) + +print(result) + +========================================================================== + +Exercise 9: + +demand = [] +for buyer_values in buyers.values(): +  demand = demand + buyer_values +demand = sorted(demand, reverse=True) + +supply = [] +for seller_values in sellers.values(): +  supply = supply + seller_values +supply = sorted(supply, reverse=False) + +quantity_sold = 0 +for buyer_value, supplyer_value in zip(demand, supply): +  quantity_sold += buyer_value >= supplyer_value +  +print(quantity_sold) diff --git a/materials/homework/week 3/Exercise_3.1.py b/materials/homework/week 3/Exercise_3.1.py new file mode 100644 index 0000000..550a711 --- /dev/null +++ b/materials/homework/week 3/Exercise_3.1.py @@ -0,0 +1,38 @@ +""" +Write a function called 'main', that accepts two integer values, 'minimum' and +'maximum', as arguments. + +The function should return a dictionary. The keys of the dictionary are tuples +for all possible combinations of integers between 'minimum' and 'maximum' +(endpoints included). + +The values of the dictionary are the result of the subtraction of the +two integers in the corresponding key. + +For example: +If we are calling your function as: +main(2, 4) +then it should return: +{(2, 2): 0, (2, 3): -1, (2, 4): -2, (3, 2): 1, (3, 3): 0, (3, 4): -1, (4, 2): 2, (4, 3): 1, (4, 4): 0} +""" + +# Hint 1: Let's define 'main' as a function taking two positional arguments. + +# Hint 2: If we're going to populate a dictionary with key-value pairs, we +# might as well define an empty dictionary in the first line inside the +# function. + +# Hint 3: How do we find all possible combinations of integers between 'minimum' +# and 'maximum'? One way to do it would be by using nested for loops, each +# having an independent running variable going from 'minimum' to 'maximum'. + +# Hint 4: the 'range(x, y)' function call gives you a collection of integers +# from x to y-1, which you can iterate over in a for loop. Use this function +# call in each of the loops, but make sure to substitute the correct arguments +# for 'x' and 'y'. + +# Hint 5: You can build the requested tuple in the inside loop, use it as a +# new key in the dictionary we are populating, and calculate the value that +# corresponds to the new key. + +# Hint 6: Don't forget to return the dictionary at the end. diff --git a/materials/homework/week 3/Exercise_3.2.py b/materials/homework/week 3/Exercise_3.2.py new file mode 100644 index 0000000..8f0b51c --- /dev/null +++ b/materials/homework/week 3/Exercise_3.2.py @@ -0,0 +1,33 @@ +""" +Write a function called 'main' that accepts an arbitrary number of keyword +arguments. You can assume that the value of every keyword argument is an +integer. + +The function should return a dictionary. The keys of the dictionary should be +the names of the keyword arguments. The values should be the remainders that +you get when you divide the keyword argument value by 5. + +Make sure that the dictionary values are integers. You may need to convert them. + +For example: +If we are calling your function as: +main(mango=7, apple=9, lime=3) +then the function should return: +{'mango': 2, 'apple': 4, 'lime': 3} +""" + +# Hint 1: Let us write the function definition line first. How do we receive +# an arbitrary number of keyword arguments in a function? What kind of data +# structure will these arguments be stored in? + +# Hint 2: We need to return a dictionary, so we might as well make an empty one +# at the start of the function. Let's call it 'x'. + +# Hint 3: 'x' needs to be populated by looping over the data structure that +# contains the received keyword argument names and values. In each iteration of +# the loop, we'll get the remainder from the division of the keyword argument +# value and 5, and use that -- along with the keyword argument +# name -- to create a new key-value pair in 'x'. Use the 'int' function to +# convert the remainders to integers, just in case they are not. + +# Hint 4: Don't forget to return 'x' at the end. diff --git a/materials/homework/week 3/Exercise_3.3.py b/materials/homework/week 3/Exercise_3.3.py new file mode 100644 index 0000000..625a799 --- /dev/null +++ b/materials/homework/week 3/Exercise_3.3.py @@ -0,0 +1,38 @@ +""" +Write a function called 'main' that takes any number of positional arguments +as inputs. In addition, it should also take an optional keyword argument that +has a default integer value of 16. The keyword argument should be named +'allowed_value'. + +The positional arguments are all dictionaries. The keys and values of these +dictionaries are all integers. Each dictionary key is unique across all the +input dictionaries. + +Your function should return a single dictionary that has all the key-value +pairs from every input dictionary, provided that the value +equals the integer stored in 'allowed_value'. + +For example: +If we call your function as: +main({88: 1, 83: 19}, {58: 15, 52: 18, 99: 16, 49: 16}) +then your function should return: +{99: 16, 49: 16} +""" + +# Hint 1: The function definition line is tricky in this one. We need to accept +# an arbitrary number of positional arguments, and we also have a keyword +# argument with a very specific name ('allowed_value') and a default value +# of 16. + +# Hint 2: The return value is a dictionary, so let's create an empty one in the +# first line of the function. I'll call it 'x'. + +# Hint 3: We have to loop through the positional arguments collection, and then +# we have to loop through the key-value pairs of each argument (since the +# positional arguments are themselves dictionaries). + +# Hint 4: As we are iterating through the key-value pairs, we can examine the +# relation of the value to the keyword argument 'allowed_value', and decide +# whether to include the key-value pair in 'x', or not. + +# Hint 5: Don't forget to return 'x' at the end. diff --git a/materials/homework/week 3/Exercise_3.4.py b/materials/homework/week 3/Exercise_3.4.py new file mode 100644 index 0000000..6f40f80 --- /dev/null +++ b/materials/homework/week 3/Exercise_3.4.py @@ -0,0 +1,39 @@ +""" +Write a function called 'main' that takes two arguments: +(1) a list of values that can be integers (int), floats (float), strings +(str), or booleans (bool), +(2) an optional keyword argument called 'excluded_type' that has a default +value of int as a Python data type. + +Your function should return another list that has all the elements of the input +list (in the same order), except for those pairs where the type of the element +equals the Python data type stored in 'excluded_type'. + +Warning: +An optional keyword argument doesn't have to be specified during a function +call, but that doesn't mean that it is never specified! Thus, the keyword +argument's value as the function is executed may sometimes be different from its +default value. + +For example: +If we call your function as: +main([3.5, True, 3.5, 0, 8, 0, 7.0, 'False', True, 3.5]) +then your function should return the list: +[3.5, True, 3.5, 7.0, 'False', True, 3.5] +""" + +# Hint 1: What is most interesting in this exercise is that we are dealing with +# Python data types as arguments that are passed around in function calls. So +# make sure that when you define the 'main' function, you give it a keyword +# argument called 'excluded_type' that has a default value of int +# (as a Python data type name) and not 'int' as a string! + +# Hint 2: Otherwise, the exercise is rather standard: create an empty list, +# loop through the elements of the first function argument, decide whether +# a given element should be included in the result list, append it to the result +# list if necessary, and return the list at the end. + +# Hint 3: Remember: you can check the type of a value with the built-in 'type' +# function. Moreover, the 'type' function has a return value that you can +# directly compare to what is stored inside the 'excluded_type' keyword +# argument. diff --git a/materials/homework/week 3/Exercise_3.5.py b/materials/homework/week 3/Exercise_3.5.py new file mode 100644 index 0000000..d675bfd --- /dev/null +++ b/materials/homework/week 3/Exercise_3.5.py @@ -0,0 +1,51 @@ +""" +Write a function called 'main', that accepts an unlimited number of arguments. +They are all integers and you can assume they are all different. + +The function should return a dictionary. The keys of the dictionary should be +the arguments that are passed to the function. The values will be lists of +those passed arguments that are smaller than the key, and that the key +can be divided by. The lists must be sorted in decreasing order. + +For example: +If we are calling your function as: +main(1, 10, 5, 17, 12, 19, 18, 16) +then the function should return (remember the order of the keys does not matter): +{12: [1], 18: [1], 17: [1], 16: [1], 10: [5, 1], 5: [1], 1: [], 19: [1]} +""" + + + + + + + + + + + + + +# Hint 1: Let us write the function definition line first. How do we receive +# an arbitrary number of positional arguments in a function? What kind of data +# structure will these arguments be stored in? + +# Hint 2: We'll populate a dictionary with all kinds of data in this exercise. +# For now, let's just create an empty one and call it something. I'll call it +# 'x', because that's short. + +# Hint 3: Let's iterate through the collection of arguments that the function +# has received. + +# Hint 4: The function argument in the current iteration will be a key in 'x'. +# The corresponding value will be a list of some kind. So let's create an empty +# list as the first action within each round of iteration. I'll call it 'y'. +# Because that's short, too. + +# Hint 5: The value to each key should be a list of those arguments that are +# (1) smaller than the key and (2) yield a zero remainder when we divide the +# key with them. So why don't we loop through all the arguments (again), and +# only append those to 'y' that satisfy these two conditions? + +# Hint 6: Once we have the right list elements, let's sort them and append the +# key-value pair to 'x'. What a long exercise! diff --git a/materials/homework/week 3/Exercise_3.6.py b/materials/homework/week 3/Exercise_3.6.py new file mode 100644 index 0000000..8d89202 --- /dev/null +++ b/materials/homework/week 3/Exercise_3.6.py @@ -0,0 +1,48 @@ +""" +Write a function called 'main' that accepts a list of integers. This is a list +with the sales volumes of all the firms in a market. + +The function should return the decrease in the Herfindahl-Hirschman Index (HHI) +as an integer when a firm with a sales volume of 40 enters the +market, while the sales volumes of the other firms stay the same. + +As a reminder, the HHI is a measure of market concentration. It is the sum of +the squares of the percentage market shares of all firms in the market. +Percentage market shares are rounded to whole numbers before the HHI +calculation. The HHI is therefore always an integer between 0 and 10,000. + +For example: +If we are calling your function as: +main([47, 21, 27, 29, 11, 6, 18]) +then it should return the integer: +224 +""" + +# Hint 1: Let's define a function first that takes a list as a positional +# argument. Calling the argument 'sales_before_entry' is probably helpful. + +# Hint 2: It's clear that we will have to calculate the HHI twice. Once with +# the new entrant's sales volume, and once without. The classy way to write +# this would be to define an inner function that calculates the HHI for any +# list of sales volumes, and then call that inner function twice from the outer +# function with different arguments. + +# Hint 3: Let's be classy, and define an inner function called 'calculate_hhi' +# that takes a list as a positional argument. + +# Hint 4: The inner function will return an integer as the HHI value. Let's call +# that integer 'hhi' and set it to zero at the start of the inner function. + +# Hint 5: We're calculating the sum of squared market shares, right? +# So we definitely need to know total sales. How do we calculate total sales +# from a list of sales volumes? There's a handy function just for this purpose! + +# Hint 6: OK, so we have total sales! It shouldn't be hard to loop +# through the sales volumes, calculate the percentage market share of each +# company, round it to a whole number, square it, and add it to 'hhi'. + +# Hint 7: We're still in the inner function! Don't forget to return 'hhi'. + +# Hint 8: Now back to the outer function 'main'! Call the inner function once +# with 'sales_before_entry', and once with 'sales_before_entry' plus 40 +# as the last element. Return the difference from 'main' and go get a coffee! diff --git a/materials/homework/week 3/Exercise_3.7.py b/materials/homework/week 3/Exercise_3.7.py new file mode 100644 index 0000000..60120dc --- /dev/null +++ b/materials/homework/week 3/Exercise_3.7.py @@ -0,0 +1,33 @@ +""" +Write a function called 'main' that takes two arguments: +(1) a 5-character-long string made up of 3 symbols and 2 spaces in between them, + like this: "$ * #" +(2) a one-character optional keyword argument called 'winning_symbol' that + has a default string value of '*'. + +Your function should return another string, which can take one of two possible +values. + +If all 3 input symbols are equal to the current value of 'winning_symbol', +then the function should return: +'[S]-BINGO!!!' +where [S] is replaced by the symbol in 'winning_symbol' + +If the symbols are not equal to 'winning_symbol', then the return value +should be: '--' + +For example: +If we call your function as: +main('$ $ $', winning_symbol='$') +then your function should return the string: +$-BINGO!!! +""" + +# Hint 1: Start with the function definition line. Make sure to define the +# keyword argument with the right name and default value. + +# Hint 2: Let's make a string with 3 symbols (and 2 spaces in between) that are +# equal to whatever is contained in the keyword argument 'winning_symbol'. +# This is what we are trying to match the first function argument with. + +# Hint 3: Decide if there is a match, and return the appropriate string. diff --git a/materials/homework/week 3/Exercise_3.8.py b/materials/homework/week 3/Exercise_3.8.py new file mode 100644 index 0000000..41f1ff9 --- /dev/null +++ b/materials/homework/week 3/Exercise_3.8.py @@ -0,0 +1,37 @@ +""" +Write a function called 'main' that accepts two lists of integers as positional +arguments. You can assume that the lists are equally long. + +The function should return another list that has the same number of elements as +either of the two input lists. In each position, the returned list should +contain the smaller of the corresponding elements in the input lists. + +If the corresponding input list elements happen to be equal, the returned list +should contain the null value None in that position. + +Consider using the 'zip' function for looping through the lists. + +For example: +If we are calling your function as: +main(([3, 9, 7, 0], [3, 5, 9, 8])) +then the function should return: +[None, 5, 7, 0] +""" + +# Hint 1: Let us write the function definition line first. We can call the two +# positional arguments 'list_1' and 'list_2'. + +# Hint 2: Since the return value is a list, we might as well create an empty +# one in the first line inside the function. + +# Hint 3: Here comes the interesting part. We want to iterate through the two +# lists in parallel. Let's use the 'zip' function to create an iterable +# collection of pairs of list elements, and unpack the pairs in the for loop +# into two variables. + +# Hint 4: In each iteration, append the smaller variable value to the result +# list. Unless they are equal, of course, in which case you should append the +# None value. Pay attention: the null value None is not the same as the +# string 'None'! + +# Hint 5: Don't forget to return the result list. diff --git a/materials/homework/week 3/Exercise_3.9.py b/materials/homework/week 3/Exercise_3.9.py new file mode 100644 index 0000000..6c386d4 --- /dev/null +++ b/materials/homework/week 3/Exercise_3.9.py @@ -0,0 +1,15 @@ +""" +Assume there is already a variable called 'integer_list' containing +a list of integers. + +Apply the lambda function lambda x: 5 * x + 6 +to all elements of the list and print out the sum of the results as an integer. + +For example: +If integer_list = [9, 8, -6, 7, -10, 6, 0, -6, 4, 9, 8, 7, -4, -3, 8, 5, 8] +your program should print: +352 +""" + +# Hint 1: This one is a one-liner. Review our discussion of the 'map' function +# in the lecture and you'll see why. diff --git a/materials/homework/week 3/Solutions week 3.txt b/materials/homework/week 3/Solutions week 3.txt new file mode 100644 index 0000000..220db64 --- /dev/null +++ b/materials/homework/week 3/Solutions week 3.txt @@ -0,0 +1,102 @@ +Solutions week 3: + +The below are suggested solutions; there are typically many ways to implement ideas in code. + +========================================================================== + +Exercise 1: + +def main(minimum, maximum): + result = {} + for first in range(minimum, maximum + 1): + for second in range(minimum, maximum + 1): + result[(first, second)] = first - second + return result + +========================================================================== + +Exercise 2: + +def main(**kwargs): + x = {} + for key, value in kwargs.items(): + x[key] = int(value % 5) + return x + +========================================================================== + +Exercise 3: + +def main(*args, allowed_value=16): + x = {} + for arg in args: + for key, value in arg.items(): + if value == allowed_value: + x[key] = value + return x + +========================================================================== +Exercise 4: + +def main(value_list, excluded_type=int): + x = [] + for item in value_list: + if type(item) != excluded_type: + x.append(item) + return x + +========================================================================== +Exercise 5: + +def main(*args): + x = {} + for key in args: + y = [] + for number in args: + if number < key and key % number == 0: + y.append(number) + x[key] = sorted(y, reverse=True) + return x + +========================================================================== + +Exercise 6: + +def main(sales_before_entry): + def calculate_hhi(sales_volumes): + total_sales = sum(sales_volumes) + hhi = 0 + for volume in sales_volumes: + hhi += round(100 * volume / total_sales)**2 + return hhi + + hhi_before_entry = calculate_hhi(sales_before_entry) + hhi_after_entry = calculate_hhi(sales_before_entry + [40]) + + return hhi_before_entry - hhi_after_entry + +========================================================================== + +Exercise 7: + +def main(symbols, winning_symbol="*"): + pattern = 2 * (winning_symbol + " ") + winning_symbol + match = winning_symbol + "-BINGO!!!" + no_match = "--" + return match if symbols == pattern else no_match + +========================================================================== + +Exercise 8: + +def main(list_1, list_2): + result = [] + for first, second in zip(list_1, list_2): + result.append(None if first == second else min(first, second)) + return result + +========================================================================== + +Exercise 9: + +print(sum(map(lambda x: 5 * x + 6, integer_list))) \ No newline at end of file diff --git a/pipelines/ai_sections/common.py b/pipelines/ai_sections/common.py index fe4aa92..484e795 100644 --- a/pipelines/ai_sections/common.py +++ b/pipelines/ai_sections/common.py @@ -53,6 +53,16 @@ def sanitize_topic_context(card: dict[str, Any]) -> dict[str, Any]: } ) + homework_context = [] + for snippet in sections.get("homework_snippets", [])[:2]: + homework_context.append( + { + "topic": snippet.get("topic", ""), + "source": trim_lines(snippet.get("source", ""), 8), + "outputs": [compact_text(out, 160) for out in (snippet.get("outputs") or [])[:2]], + } + ) + traps = [] for trap in card.get("trap_patterns", [])[:3]: traps.append( @@ -73,6 +83,7 @@ def sanitize_topic_context(card: dict[str, Any]) -> dict[str, Any]: "lecture_context": lecture_context, "exam_context": exam_context, "notebook_context": notebook_context, + "homework_context": homework_context, "trap_patterns": traps, } diff --git a/pipelines/shared/study_database.py b/pipelines/shared/study_database.py index 8296cdc..c9c60b5 100644 --- a/pipelines/shared/study_database.py +++ b/pipelines/shared/study_database.py @@ -42,6 +42,7 @@ def _empty_week_record(week: int) -> dict[str, Any]: "lecture_questions": [], }, "notebook_cells": [], + "homework_cells": [], "sources": [], } @@ -84,6 +85,15 @@ def build_study_db_from_monolith(data: dict[str, Any]) -> dict[str, Any]: week_rec = week_map.setdefault(week, _empty_week_record(week)) week_rec["notebook_cells"].append(cell) + for cell in _safe_list(data.get("homeworks")): + if not isinstance(cell, dict): + continue + week = _as_int(cell.get("week")) + if week is None: + continue + week_rec = week_map.setdefault(week, _empty_week_record(week)) + week_rec["homework_cells"].append(cell) + for source in _safe_list(meta.get("sources")): if not isinstance(source, str): continue @@ -158,6 +168,7 @@ def flatten_study_db_for_pipeline(db: dict[str, Any]) -> dict[str, Any]: lectures: list[dict[str, Any]] = [] notebooks: list[dict[str, Any]] = [] + homeworks: list[dict[str, Any]] = [] for week_rec in weeks: week = _as_int(week_rec.get("week")) @@ -181,7 +192,15 @@ def flatten_study_db_for_pipeline(db: dict[str, Any]) -> dict[str, Any]: materialized["week"] = week notebooks.append(materialized) + for cell in _safe_list(week_rec.get("homework_cells")): + if not isinstance(cell, dict): + continue + materialized = dict(cell) + materialized["week"] = week + homeworks.append(materialized) + notebooks.sort(key=lambda item: (_as_int(item.get("week")) or 9999, int(item.get("cell_index") or 0))) + homeworks.sort(key=lambda item: (_as_int(item.get("week")) or 9999, int(item.get("cell_index") or 0))) assessments = db.get("assessments", {}) if isinstance(db.get("assessments"), dict) else {} exams = [item for item in _safe_list(assessments.get("exams")) if isinstance(item, dict)] @@ -196,6 +215,7 @@ def flatten_study_db_for_pipeline(db: dict[str, Any]) -> dict[str, Any]: }, "lectures": lectures, "notebooks": notebooks, + "homeworks": homeworks, "exams": exams, "key_exam_patterns_and_traps": _safe_list(knowledge.get("key_exam_patterns_and_traps")), "topic_analysis": knowledge.get("topic_analysis", {}), @@ -209,6 +229,7 @@ def _flatten_v3_study_db_for_pipeline(db: dict[str, Any]) -> dict[str, Any]: lectures: list[dict[str, Any]] = [] notebooks: list[dict[str, Any]] = [] + homeworks: list[dict[str, Any]] = [] for week_rec in weeks: week = _as_int(week_rec.get("week")) @@ -294,7 +315,15 @@ def _flatten_v3_study_db_for_pipeline(db: dict[str, Any]) -> dict[str, Any]: } ) + for cell in _safe_list(week_rec.get("homework_cells")): + if not isinstance(cell, dict): + continue + materialized = dict(cell) + materialized["week"] = week + homeworks.append(materialized) + notebooks.sort(key=lambda item: (_as_int(item.get("week")) or 9999, int(item.get("cell_index") or 0))) + homeworks.sort(key=lambda item: (_as_int(item.get("week")) or 9999, int(item.get("cell_index") or 0))) assessments = db.get("assessments", {}) if isinstance(db.get("assessments"), dict) else {} exams = [item for item in _safe_list(assessments.get("exams")) if isinstance(item, dict)] @@ -309,6 +338,7 @@ def _flatten_v3_study_db_for_pipeline(db: dict[str, Any]) -> dict[str, Any]: }, "lectures": lectures, "notebooks": notebooks, + "homeworks": homeworks, "exams": exams, "key_exam_patterns_and_traps": _safe_list(knowledge.get("key_exam_patterns_and_traps")), "topic_analysis": knowledge.get("topic_analysis", {}), diff --git a/pipelines/study_database/curation.py b/pipelines/study_database/curation.py index 47db86f..87c9c4c 100644 --- a/pipelines/study_database/curation.py +++ b/pipelines/study_database/curation.py @@ -43,6 +43,7 @@ def normalize_week_payload(raw_payload: dict[str, Any]) -> dict[str, Any]: concepts = _safe_list(lecture.get("concepts")) lecture_questions = _safe_list(lecture.get("lecture_questions")) notebook_cells = _safe_list(raw_payload.get("notebook_cells")) + homework_cells = _safe_list(raw_payload.get("homework_cells")) normalized = { "week": week, @@ -52,6 +53,7 @@ def normalize_week_payload(raw_payload: dict[str, Any]) -> dict[str, Any]: "lecture_questions": [deepcopy(item) for item in lecture_questions if isinstance(item, dict)], }, "notebook_cells": [deepcopy(item) for item in notebook_cells if isinstance(item, dict)], + "homework_cells": [deepcopy(item) for item in homework_cells if isinstance(item, dict)], "sources": [str(source).strip() for source in _safe_list(raw_payload.get("sources")) if str(source).strip()], } @@ -65,9 +67,15 @@ def normalize_week_payload(raw_payload: dict[str, Any]) -> dict[str, Any]: cell.setdefault("cell_type", "code") cell.setdefault("outputs", []) cell.setdefault("is_advanced_optional", False) + for cell in normalized["homework_cells"]: + cell["week"] = week + cell.setdefault("topic", "") + cell.setdefault("cell_type", "code") + cell.setdefault("outputs", []) + cell.setdefault("is_advanced_optional", False) - if not normalized["lecture"]["concepts"] and not normalized["notebook_cells"]: - raise WeekCurationError("Week payload is empty: provide at least lecture concepts or notebook cells.") + if not normalized["lecture"]["concepts"] and not normalized["notebook_cells"] and not normalized["homework_cells"]: + raise WeekCurationError("Week payload is empty: provide at least lecture concepts, notebook cells, or homework cells.") return normalized @@ -156,6 +164,7 @@ def curate_week_payload(payload: dict[str, Any], *, model: str = MODEL_DEFAULT) "lecture_questions": lecture_curated["lecture_questions"], }, "notebook_cells": notebook_curated, + "homework_cells": normalized["homework_cells"], "sources": normalized["sources"], "curation_meta": { "generator": "gemini-cli", @@ -169,6 +178,8 @@ def curate_week_payload(payload: dict[str, Any], *, model: str = MODEL_DEFAULT) question["week"] = week for cell in curated["notebook_cells"]: cell["week"] = week + for cell in curated["homework_cells"]: + cell["week"] = week report = { "week": week, @@ -182,5 +193,8 @@ def curate_week_payload(payload: dict[str, Any], *, model: str = MODEL_DEFAULT) "quality_notes": lecture_report["quality_notes"], }, "notebooks": notebook_report, + "homework": { + "total_cells": len(normalized["homework_cells"]), + }, } return curated, report diff --git a/pipelines/study_database/validators.py b/pipelines/study_database/validators.py index ad41e27..efc48f5 100644 --- a/pipelines/study_database/validators.py +++ b/pipelines/study_database/validators.py @@ -90,25 +90,34 @@ def analyze_week_payload(payload: dict[str, Any]) -> dict[str, list[str]]: f"`lecture.lecture_questions[{index}].correct={correct!r}` is not present in options: {sorted(valid_keys)}" ) + def bucket_label(bucket: str) -> str: + return bucket.replace("_cells", " cell") + + def validate_cells(bucket: str, cells: list[Any]) -> None: + seen_cell_indexes: set[int] = set() + for index, cell in enumerate(cells, start=1): + if not isinstance(cell, dict): + errors.append(f"`{bucket}[{index}]` must be an object.") + continue + cell_index = _as_positive_int(cell.get("cell_index")) + if cell_index is None: + errors.append(f"`{bucket}[{index}].cell_index` must be a positive integer.") + continue + if cell_index in seen_cell_indexes: + errors.append(f"Duplicate {bucket_label(bucket)}_index found: {cell_index}") + seen_cell_indexes.add(cell_index) + + cell_type = _safe_str(cell.get("cell_type")).lower() + if cell_type and cell_type not in {"code", "markdown", "raw"}: + warnings.append( + f"`{bucket}[{index}].cell_type={cell_type!r}` is unusual (expected code/markdown/raw)." + ) + notebook_cells = _safe_list(payload.get("notebook_cells")) - seen_cell_indexes: set[int] = set() - for index, cell in enumerate(notebook_cells, start=1): - if not isinstance(cell, dict): - errors.append(f"`notebook_cells[{index}]` must be an object.") - continue - cell_index = _as_positive_int(cell.get("cell_index")) - if cell_index is None: - errors.append(f"`notebook_cells[{index}].cell_index` must be a positive integer.") - continue - if cell_index in seen_cell_indexes: - errors.append(f"Duplicate notebook cell_index found: {cell_index}") - seen_cell_indexes.add(cell_index) - - cell_type = _safe_str(cell.get("cell_type")).lower() - if cell_type and cell_type not in {"code", "markdown", "raw"}: - warnings.append( - f"`notebook_cells[{index}].cell_type={cell_type!r}` is unusual (expected code/markdown/raw)." - ) + validate_cells("notebook_cells", notebook_cells) + + homework_cells = _safe_list(payload.get("homework_cells")) + validate_cells("homework_cells", homework_cells) sources = [str(source).strip() for source in _safe_list(payload.get("sources")) if str(source).strip()] seen_sources: set[str] = set() @@ -119,8 +128,8 @@ def analyze_week_payload(payload: dict[str, Any]) -> dict[str, list[str]]: continue seen_sources.add(normalized) - if not concepts and not notebook_cells: - errors.append("Payload must include at least one lecture concept or one notebook cell.") + if not concepts and not notebook_cells and not homework_cells: + errors.append("Payload must include at least one lecture concept, notebook cell, or homework cell.") return { "errors": errors, diff --git a/scripts/exam_coverage_audit.py b/scripts/exam_coverage_audit.py new file mode 100644 index 0000000..bbdf48b --- /dev/null +++ b/scripts/exam_coverage_audit.py @@ -0,0 +1,419 @@ +from __future__ import annotations + +import argparse +import json +import os +import subprocess +from pathlib import Path + + +ROOT = Path(__file__).resolve().parents[1] +COURSE_DIR = ROOT.parent / "course_files_after_midterm" +PRACTICE_EXAMS_DIR = COURSE_DIR / "practice_exams_previous_years" +DEFAULT_TMP_DIR = ROOT / "tmp" / "exam_coverage_audit" +TOPIC_CARDS_PATH = ROOT / "topic_cards.json" + +EXAM_SOURCES = [ + { + "exam_id": "sample-final-plus-answers", + "title": "2025 Sample Final Plus Answers", + "pdf_path": COURSE_DIR / "Sample Final plus answers.pdf", + "expected_questions": 24, + "group": "current-year", + }, + { + "exam_id": "final-exam-solutions-for-python-programming-62oop21", + "title": "2022 Final Exam", + "pdf_path": PRACTICE_EXAMS_DIR / "final-exam-solutions-for-python-programming-62oop21.pdf", + "expected_questions": 24, + "group": "previous-years", + }, + { + "exam_id": "final-exam-solutions-for-python-programming-course-code-308088-308234", + "title": "2022 Final Exam Duplicate Copy", + "pdf_path": PRACTICE_EXAMS_DIR / "final-exam-solutions-for-python-programming-course-code-308088-308234.pdf", + "expected_questions": 24, + "group": "previous-years", + "duplicate_of": "final-exam-solutions-for-python-programming-62oop21", + }, + { + "exam_id": "final-exam-study-guide-trial-python-basics-2023", + "title": "2023 Trial Final Study Guide", + "pdf_path": PRACTICE_EXAMS_DIR / "final-exam-study-guide-trial-python-basics-2023.pdf", + "expected_questions": 24, + "group": "previous-years", + }, + { + "exam_id": "introduction-to-python-trial-final-exam-solutions-py22", + "title": "2024 Trial Final", + "pdf_path": PRACTICE_EXAMS_DIR / "introduction-to-python-trial-final-exam-solutions-py22.pdf", + "expected_questions": 24, + "group": "previous-years", + }, + { + "exam_id": "resit-exam-guidelines-for-intro-to-python-6013b0470y-july-2023", + "title": "2023 Resit Exam Guidelines", + "pdf_path": PRACTICE_EXAMS_DIR / "resit-exam-guidelines-for-intro-to-python-6013b0470y-july-2023.pdf", + "expected_questions": 24, + "group": "previous-years", + }, + { + "exam_id": "resit-solutions-for-introduction-to-python-35761538", + "title": "2023 Resit Solutions", + "pdf_path": PRACTICE_EXAMS_DIR / "resit-solutions-for-introduction-to-python-35761538.pdf", + "expected_questions": 24, + "group": "previous-years", + }, + { + "exam_id": "trial-final-exam-solutions-introduction-to-python-3077951", + "title": "Trial Final Later-Course Focus", + "pdf_path": PRACTICE_EXAMS_DIR / "trial-final-exam-solutions-introduction-to-python-3077951.pdf", + "expected_questions": 24, + "group": "previous-years", + }, +] + + +def parse_args() -> argparse.Namespace: + parser = argparse.ArgumentParser(description="Prepare and validate the vision-first exam coverage audit.") + subparsers = parser.add_subparsers(dest="command", required=True) + + prepare = subparsers.add_parser("prepare", help="Render unique exam PDFs and write selectable-item audit packets.") + prepare.add_argument("--tmp-dir", type=Path, default=DEFAULT_TMP_DIR) + prepare.add_argument("--dpi", type=int, default=160) + prepare.add_argument("--overwrite", action="store_true") + + summary = subparsers.add_parser("summary", help="Print selectable-item counts and unique exam metadata.") + summary.add_argument("--tmp-dir", type=Path, default=DEFAULT_TMP_DIR) + + validate = subparsers.add_parser("validate-findings", help="Validate a findings JSON file against selectable item IDs.") + validate.add_argument("--input", type=Path, required=True) + + return parser.parse_args() + + +def normalize_newlines(text: str | None) -> str: + return str(text or "").replace("\r\n", "\n").replace("\r", "\n") + + +def looks_code_like(text: str | None) -> bool: + value = str(text or "").strip() + if not value: + return False + if "\n" in value: + return True + code_signals = ["=", "(", ")", "[", "]", "{", "}", ":", "+", "-", "*", "/", "%", "."] + code_keywords = ["print", "for ", "if ", "while ", "def ", "return", "import ", "from ", "lambda", "range", "len", "sorted"] + lower = value.lower() + return any(signal in value for signal in code_signals) or any(lower.startswith(kw) or f" {kw}" in lower for kw in code_keywords) + + +def is_low_value_snippet(text: str | None) -> bool: + value = str(text or "").strip() + if not value: + return True + if "\n" in value: + return False + lower = value.lower() + if lower.startswith("#"): + return True + low_phrases = [ + "below you will find", + "the following", + "function definitions start", + "you call functions", + "dictionaries are", + "global and local names", + ] + if any(phrase in lower for phrase in low_phrases) and not looks_code_like(value): + return True + return not looks_code_like(value) and len(value.split()) <= 8 + + +def load_topic_cards(path: Path = TOPIC_CARDS_PATH) -> list[dict]: + with path.open("r", encoding="utf-8") as handle: + return json.load(handle)["cards"] + + +def useful_lecture_snippets(card: dict) -> list[dict]: + useful = [] + for snippet in card.get("sections", {}).get("lecture_snippets", []): + filtered_examples = [example for example in snippet.get("code_examples", []) if not is_low_value_snippet(example.get("code", ""))] + item = {**snippet, "code_examples": filtered_examples} + if item.get("explanation") or item.get("question") or filtered_examples: + useful.append(item) + return useful + + +def useful_notebook_snippets(card: dict) -> list[dict]: + useful = [] + for snippet in card.get("sections", {}).get("notebook_snippets", []): + source = str(snippet.get("source", "")) + has_print_call = "print(" in source + has_outputs = bool(snippet.get("outputs")) + if not is_low_value_snippet(source) and (not has_print_call or has_outputs): + useful.append(snippet) + return useful + + +def normalize_common_questions(card: dict) -> list[dict]: + section = card.get("sections", {}).get("ai_common_questions", {}) or {} + items = section.get("items", []) + if items: + normalized = [] + for index, item in enumerate(items, start=1): + if not isinstance(item, dict): + continue + summary = str(item.get("summary") or item.get("question") or "").strip() + detail = str(item.get("detail") or item.get("answer") or "").strip() + extra = str(item.get("extra") or item.get("additional_info") or item.get("why") or "").strip() + code = normalize_newlines(item.get("code")).strip() + table = item.get("table") if isinstance(item.get("table"), dict) else None + if not any([summary, detail, extra, code, table]): + continue + normalized.append( + { + "id": str(item.get("id") or f"aiq-{index}"), + "summary": summary, + "detail": detail, + "extra": extra, + "code": code, + "table": table, + } + ) + return normalized + return [ + {"id": f"aiq-{index}", "summary": str(bullet).strip(), "detail": "", "extra": "", "code": "", "table": None} + for index, bullet in enumerate(section.get("bullets", []), start=1) + if str(bullet).strip() + ] + + +def key_point_groups(card: dict) -> list[dict]: + groups = [] + for index, item in enumerate(card.get("sections", {}).get("key_points_to_remember", []), start=1): + text = str(item.get("text") or "").strip() + if not text: + continue + point_id = str(item.get("id") or f"kp-{index}").strip() + details = [] + for detail_index, detail in enumerate(item.get("details") or [], start=1): + if not isinstance(detail, dict): + continue + detail_id = str(detail.get("id") or f"{point_id}-d{detail_index}").strip() + detail_text = str(detail.get("text") or "").strip() + detail_code = normalize_newlines(detail.get("code")).strip() + detail_table = detail.get("table") if isinstance(detail.get("table"), dict) else None + if not detail_id or not any([detail_text, detail_code, detail_table]): + continue + details.append( + { + "id": detail_id, + "title": str(detail.get("title") or "Optional detail").strip(), + "kind": str(detail.get("kind") or "example").strip(), + "text": detail_text, + "code": detail_code, + "table": detail_table, + } + ) + groups.append( + { + "id": point_id, + "text": text, + "subtopic_id": str(item.get("subtopic_id") or "").strip(), + "subtopic_title": str(item.get("subtopic_title") or "").strip(), + "details": details, + } + ) + return groups + + +def build_source_items(card: dict) -> list[dict]: + items = [] + for item in card.get("sections", {}).get("exam_questions", []): + items.append({"id": item.get("id"), "source_type": "exam", "priority": 0, "item": item}) + for item in useful_lecture_snippets(card): + items.append({"id": item.get("id"), "source_type": "lecture", "priority": 1, "item": item}) + for item in useful_notebook_snippets(card): + items.append({"id": item.get("id"), "source_type": "notebook", "priority": 2, "item": item}) + return sorted(items, key=lambda entry: entry["priority"]) + + +def get_source_split(card: dict) -> tuple[list[dict], list[dict]]: + all_items = build_source_items(card) + by_id = {item["id"]: item for item in all_items if item.get("id")} + recommended_ids = [item_id for item_id in card.get("sections", {}).get("recommended_ids", []) if item_id in by_id] + recommended = [] + for item_id in recommended_ids: + if not any(existing["id"] == item_id for existing in recommended): + recommended.append(by_id[item_id]) + if not recommended and all_items: + fallback = [item for item in all_items if item["source_type"] == "exam"][:4] + extra = [item for item in all_items if item["source_type"] != "exam"][: max(0, 6 - len(fallback))] + recommended = fallback + extra + recommended_ids_set = {item["id"] for item in recommended} + additional = [item for item in all_items if item["id"] not in recommended_ids_set] + return recommended, additional + + +def table_to_text(table: dict | None) -> str: + if not isinstance(table, dict): + return "" + headers = " | ".join(str(value or "").strip() for value in table.get("headers", [])) + rows = [" | ".join(str(value or "").strip() for value in row) for row in table.get("rows", []) if isinstance(row, list)] + return "\n".join(filter(None, [headers, *rows])) + + +def stringify_item_payload(item_type: str, payload: dict) -> str: + if item_type == "ai_common_question": + return "\n".join(filter(None, [payload.get("summary"), payload.get("detail"), payload.get("extra"), payload.get("code"), table_to_text(payload.get("table"))])) + if item_type == "key_point": + return payload.get("text", "") + if item_type == "key_point_detail": + return "\n".join(filter(None, [payload.get("title"), payload.get("text"), payload.get("code"), table_to_text(payload.get("table"))])) + if item_type == "ai_example": + return "\n".join(filter(None, [payload.get("title"), payload.get("code"), payload.get("why"), payload.get("output")])) + source_type = payload.get("source_type") + source = payload.get("item", {}) + if source_type == "exam": + options = "\n".join(source.get("options", [])) + return "\n".join(filter(None, [source.get("question"), options, source.get("correct"), source.get("explanation")])) + if source_type == "lecture": + examples = "\n".join(f"{example.get('description', '')}\n{example.get('code', '')}" for example in source.get("code_examples", [])) + return "\n".join(filter(None, [source.get("title"), source.get("explanation"), source.get("question"), examples])) + outputs = "\n".join(source.get("outputs", [])) + return "\n".join(filter(None, [source.get("title"), source.get("source"), outputs])) + + +def iter_selectable_items(cards: list[dict]) -> list[dict]: + items = [] + for card in cards: + for item in normalize_common_questions(card): + items.append(_selectable_item(card, "ai_common_question", item["id"], "aiQuestions", "direct", item)) + for group in key_point_groups(card): + items.append(_selectable_item(card, "key_point", group["id"], "keyPoints", "direct", group)) + for detail in group["details"]: + items.append(_selectable_item(card, "key_point_detail", detail["id"], "keyPoints", "detail", detail)) + for item in card.get("sections", {}).get("ai_examples", []): + item_id = str(item.get("id") or "").strip() + if item_id: + items.append(_selectable_item(card, "ai_example", item_id, "aiExamples", "direct", item)) + recommended, additional = get_source_split(card) + for bucket, source_items in [("recommended", recommended), ("additional", additional)]: + for item in source_items: + item_id = str(item.get("id") or "").strip() + if item_id: + items.append(_selectable_item(card, f"source_{item['source_type']}", item_id, bucket, "source", item)) + return items + + +def _selectable_item(card: dict, item_type: str, item_id: str, bucket: str, selection_kind: str, payload: dict) -> dict: + return { + "item_id": item_id, + "card_id": card["id"], + "topic": card.get("topic", ""), + "subtopic_id": payload.get("subtopic_id", ""), + "subtopic_title": payload.get("subtopic_title", ""), + "item_type": item_type, + "bucket": bucket, + "selection_kind": selection_kind, + "search_text": stringify_item_payload(item_type, payload), + } + + +def unique_exam_sources() -> list[dict]: + return [exam for exam in EXAM_SOURCES if not exam.get("duplicate_of")] + + +def portable_path(path: Path, *, relative_to: Path = ROOT) -> str: + return Path(os.path.relpath(path, relative_to)).as_posix() + + +def render_exam_pages(exam: dict, output_dir: Path, dpi: int, overwrite: bool) -> list[Path]: + exam_dir = output_dir / exam["exam_id"] + exam_dir.mkdir(parents=True, exist_ok=True) + prefix = exam_dir / "page" + existing_pages = sorted(exam_dir.glob("page-*.png")) + if existing_pages and not overwrite: + return existing_pages + if overwrite: + for existing in existing_pages: + existing.unlink() + command = ["pdftoppm", "-png", "-r", str(dpi), str(exam["pdf_path"]), str(prefix)] + subprocess.run(command, check=True) + return sorted(exam_dir.glob("page-*.png")) + + +def write_prepare_outputs(tmp_dir: Path, dpi: int, overwrite: bool) -> None: + tmp_dir.mkdir(parents=True, exist_ok=True) + cards = load_topic_cards() + items = iter_selectable_items(cards) + page_root = tmp_dir / "pages" + manifest = { + "topic_cards_path": portable_path(TOPIC_CARDS_PATH), + "selectable_items_path": portable_path(tmp_dir / "selectable_items.json"), + "current_repo_cards": len(cards), + "unique_exam_count": len(unique_exam_sources()), + "excluded_duplicates": [ + {"exam_id": exam["exam_id"], "duplicate_of": exam["duplicate_of"], "pdf_path": portable_path(exam["pdf_path"])} + for exam in EXAM_SOURCES + if exam.get("duplicate_of") + ], + "exams": [], + } + for exam in unique_exam_sources(): + pages = render_exam_pages(exam, page_root, dpi=dpi, overwrite=overwrite) + manifest["exams"].append( + { + "exam_id": exam["exam_id"], + "title": exam["title"], + "pdf_path": portable_path(exam["pdf_path"]), + "expected_questions": exam["expected_questions"], + "page_count": len(pages), + "page_image_paths": [portable_path(path) for path in pages], + } + ) + (tmp_dir / "selectable_items.json").write_text(json.dumps(items, indent=2), encoding="utf-8") + (tmp_dir / "manifest.json").write_text(json.dumps(manifest, indent=2), encoding="utf-8") + + +def print_summary(tmp_dir: Path) -> None: + cards = load_topic_cards() + items = iter_selectable_items(cards) + counts = {} + for item in items: + counts[item["item_type"]] = counts.get(item["item_type"], 0) + 1 + print(json.dumps({"cards": len(cards), "selectable_items": len(items), "counts_by_type": counts, "unique_exams": unique_exam_sources()}, indent=2, default=str)) + if (tmp_dir / "manifest.json").exists(): + print(f"\nPrepared manifest: {tmp_dir / 'manifest.json'}") + + +def validate_findings(path: Path) -> None: + cards = load_topic_cards() + valid_item_ids = {item["item_id"] for item in iter_selectable_items(cards)} + with path.open("r", encoding="utf-8") as handle: + findings = json.load(handle) + unknown = [] + for exam in findings.get("exams", []): + for question in exam.get("questions", []): + for item_id in question.get("evidence_item_ids", []): + if item_id not in valid_item_ids: + unknown.append((exam.get("exam_id"), question.get("question_number"), item_id)) + if unknown: + raise SystemExit("Unknown selectable item ids:\n" + "\n".join(f"{exam_id} Q{number}: {item_id}" for exam_id, number, item_id in unknown)) + print(f"Validated findings successfully: {path}") + + +def main() -> None: + args = parse_args() + if args.command == "prepare": + write_prepare_outputs(args.tmp_dir, dpi=args.dpi, overwrite=args.overwrite) + print(f"Prepared exam coverage audit packet in {args.tmp_dir}") + elif args.command == "summary": + print_summary(args.tmp_dir) + elif args.command == "validate-findings": + validate_findings(args.input) + + +if __name__ == "__main__": + main() diff --git a/scripts/integrate_homework_material.py b/scripts/integrate_homework_material.py new file mode 100644 index 0000000..d1ad930 --- /dev/null +++ b/scripts/integrate_homework_material.py @@ -0,0 +1,494 @@ +#!/usr/bin/env python3 +from __future__ import annotations +import argparse +import json +import re +from dataclasses import dataclass +from datetime import datetime, timezone +from pathlib import Path +import sys +from typing import Any +ROOT = Path(__file__).resolve().parents[1] +if str(ROOT) not in sys.path: + sys.path.insert(0, str(ROOT)) +from pipelines.shared import ( # noqa: E402 + flatten_study_db_for_pipeline, + load_study_db, + recompute_topic_analysis, + write_study_db, +) +from pipelines.topic_cards.core import ( # noqa: E402 + clean_notebook_source, + compact_text, + dedupe_list, + is_relevant, + make_id, + topic_key, +) +DEFAULT_HOMEWORK_DIR = ROOT / "materials" / "homework" +DEFAULT_STUDY_DB = ROOT / "data" / "study_db.json" +DEFAULT_TOPIC_CARDS = ROOT / "topic_cards.json" +DEFAULT_REPORT_FILE = ROOT / "data" / "curation_reports" / "homework_integration_report.json" +WEEK_DIR_RE = re.compile(r"^week\s+(\d+)$", re.IGNORECASE) +SOLUTION_BLOCK_RE = re.compile(r"^\s*Exercise\s+(\d+)\s*:\s*$", re.IGNORECASE) +EXERCISE_FILENAME_RE = re.compile(r"^Exercise(?:[_ ](?:(\d+)\.)?(\d+))?\.py$", re.IGNORECASE) +HOMEWORK_TOPIC_MAP: dict[int, dict[int, str]] = { + 1: { + 1: "arithmetic_operators", + 2: "arithmetic_operators", + 3: "arithmetic_operators", + 4: "strings", + 5: "boolean_operators", + 6: "type_conversion", + 7: "indexing", + 8: "indexing", + 9: "slicing", + }, + 2: { + 1: "dictionaries", + 2: "while_loops", + 3: "dictionaries", + 4: "enumerate", + 5: "zip", + 6: "dictionaries", + 7: "truthy_falsy", + 8: "conditions", + 9: "for_loops", + }, + 3: { + 1: "nested_loops", + 2: "keyword_args", + 3: "args_star", + 4: "default_args", + 5: "args_star", + 6: "function_factories", + 7: "default_args", + 8: "zip", + 9: "lambda", + }, +} +BONUS_TOPIC_MAP: dict[int, str] = { + 1: "indexing", +} + +HOMEWORK_CARD_TARGETS: dict[str, tuple[str, ...]] = { + "arithmetic": ("w1-operators-and-truth",), + "boolean": ("w1-operators-and-truth",), + "conversion": ("w2-conversion-and-truthiness",), + "indexing": ("w1-sequences-and-access",), + "slicing": ("w1-sequences-and-access",), + "string": ("w1-sequences-and-access",), + "dictionary": ("w2-dictionaries-and-mappings",), + "loop while": ("w2-loops",), + "loop": ("w2-loops",), + "loop nested": ("w2-loops",), + "enumerate": ("w2-loops",), + "zip": ("w2-loops",), + "falsy truthy": ("w2-conversion-and-truthiness",), + "condition": ("w2-conditions",), + "args keyword": ("w3-arguments",), + "args star": ("w3-arguments",), + "args default": ("w3-arguments",), + "factory function": ("w3-higher-order-patterns",), + "lambda": ("w3-higher-order-patterns",), +} +@dataclass(frozen=True) +class CandidateCell: + week: int + topic: str + source_text: str + origin: str +def parse_args() -> argparse.Namespace: + parser = argparse.ArgumentParser( + description="Integrate homework solution snippets into study_db homework_cells and topic_cards homework_snippets." + ) + parser.add_argument( + "--homework-dir", + type=Path, + default=DEFAULT_HOMEWORK_DIR, + help=f"Homework root directory (default: {DEFAULT_HOMEWORK_DIR}).", + ) + parser.add_argument( + "--study-db", + type=Path, + default=DEFAULT_STUDY_DB, + help=f"Path to study_db JSON (default: {DEFAULT_STUDY_DB}).", + ) + parser.add_argument( + "--topic-cards", + type=Path, + default=DEFAULT_TOPIC_CARDS, + help=f"Path to topic_cards JSON (default: {DEFAULT_TOPIC_CARDS}).", + ) + parser.add_argument( + "--report-file", + type=Path, + default=DEFAULT_REPORT_FILE, + help=f"Integration report output path (default: {DEFAULT_REPORT_FILE}).", + ) + parser.add_argument( + "--dry-run", + action="store_true", + help="Build integration result and report without writing data files.", + ) + return parser.parse_args() +def _safe_list(value: Any) -> list[Any]: + return value if isinstance(value, list) else [] +def _normalize_source(value: str) -> str: + return value.replace("\r\n", "\n").replace("\u00a0", " ").strip() +def _strip_docstring_prefix(source: str) -> str: + text = source.lstrip() + if text.startswith('"""') or text.startswith("'''"): + quote = text[:3] + end = text.find(quote, 3) + if end != -1: + return text[end + 3 :].lstrip() + return source.strip() +def _clean_solution_block(lines: list[str]) -> str: + while lines and not lines[0].strip(): + lines.pop(0) + while lines and not lines[-1].strip(): + lines.pop() + cleaned: list[str] = [] + for raw in lines: + line = raw.replace("\u00a0", " ") + if set(line.strip()) == {"="}: + continue + cleaned.append(line.rstrip()) + text = "\n".join(cleaned).strip() + return _normalize_source(text) +def parse_solution_blocks(solution_file: Path) -> dict[int, str]: + lines = solution_file.read_text(encoding="utf-8").replace("\u00a0", " ").splitlines() + by_exercise: dict[int, str] = {} + current: int | None = None + buf: list[str] = [] + def flush() -> None: + nonlocal buf + if current is None: + return + parsed = _clean_solution_block(buf) + if parsed: + by_exercise[current] = parsed + buf = [] + for line in lines: + match = SOLUTION_BLOCK_RE.match(line) + if match: + flush() + current = int(match.group(1)) + continue + if current is not None: + buf.append(line) + flush() + return by_exercise +def parse_exercise_id(file_name: str) -> int | None: + match = EXERCISE_FILENAME_RE.match(file_name) + if not match: + return None + return int(match.group(2) or 0) or None +def _week_dirs(homework_dir: Path) -> list[tuple[int, Path]]: + out: list[tuple[int, Path]] = [] + for child in homework_dir.iterdir(): + if not child.is_dir(): + continue + match = WEEK_DIR_RE.match(child.name.strip()) + if not match: + continue + out.append((int(match.group(1)), child)) + return sorted(out, key=lambda item: item[0]) +def _relative(path: Path) -> str: + try: + return str(path.relative_to(ROOT)) + except ValueError: + return str(path) +def _extract_bonus_source(path: Path) -> str: + text = _normalize_source(path.read_text(encoding="utf-8")) + stripped = _strip_docstring_prefix(text) + return stripped or text +def build_candidates(homework_dir: Path) -> tuple[list[CandidateCell], dict[int, list[str]]]: + all_candidates: list[CandidateCell] = [] + week_sources: dict[int, list[str]] = {} + for week, week_dir in _week_dirs(homework_dir): + files = sorted(path for path in week_dir.iterdir() if path.is_file() and not path.name.startswith(".")) + week_sources[week] = [_relative(path) for path in files] + solution_file = next((path for path in files if path.name.lower().startswith("solutions week ")), None) + solution_blocks = parse_solution_blocks(solution_file) if solution_file else {} + for path in files: + if path.name.lower().startswith("solutions week "): + continue + if path.name.lower().endswith("bonus_exercise_solved.py"): + source_text = _extract_bonus_source(path) + topic = BONUS_TOPIC_MAP.get(week, "homework") + if source_text: + all_candidates.append( + CandidateCell( + week=week, + topic=topic, + source_text=source_text, + origin=_relative(path), + ) + ) + continue + exercise_id = parse_exercise_id(path.name) + if exercise_id is None: + continue + topic = HOMEWORK_TOPIC_MAP.get(week, {}).get(exercise_id, "homework") + source_text = solution_blocks.get(exercise_id) + if not source_text: + continue + tagged_source = f"# source: {_relative(path)}\n{source_text}" + all_candidates.append( + CandidateCell( + week=week, + topic=topic, + source_text=_normalize_source(tagged_source), + origin=_relative(path), + ) + ) + return all_candidates, week_sources +def _index_weeks(db: dict[str, Any]) -> dict[int, dict[str, Any]]: + out: dict[int, dict[str, Any]] = {} + weeks = [item for item in _safe_list(db.get("weeks")) if isinstance(item, dict)] + db["weeks"] = weeks + for week in weeks: + try: + week_num = int(week.get("week")) + except (TypeError, ValueError): + continue + out[week_num] = week + return out +def _source_signature(topic: str, source: str) -> tuple[str, str]: + return (topic.strip().lower(), _normalize_source(source)) +def _append_unique_sources(week_rec: dict[str, Any], new_sources: list[str]) -> int: + existing = [src for src in _safe_list(week_rec.get("sources")) if isinstance(src, str)] + seen = {src.lower() for src in existing} + added = 0 + for src in new_sources: + if not src.strip(): + continue + key = src.lower() + if key in seen: + continue + existing.append(src) + seen.add(key) + added += 1 + week_rec["sources"] = existing + return added +def _append_unique_homework_cells(week_rec: dict[str, Any], candidates: list[CandidateCell]) -> int: + cells = [cell for cell in _safe_list(week_rec.get("homework_cells")) if isinstance(cell, dict)] + week_rec["homework_cells"] = cells + seen = set() + max_index = 0 + for cell in cells: + topic = str(cell.get("topic") or "") + source = str(cell.get("source") or "") + seen.add(_source_signature(topic, source)) + try: + max_index = max(max_index, int(cell.get("cell_index") or 0)) + except (TypeError, ValueError): + continue + added = 0 + for candidate in candidates: + signature = _source_signature(candidate.topic, candidate.source_text) + if signature in seen: + continue + max_index += 1 + cells.append( + { + "cell_index": max_index, + "week": candidate.week, + "cell_type": "code", + "topic": candidate.topic, + "is_advanced_optional": False, + "source": candidate.source_text, + "outputs": [], + "source_origin": candidate.origin, + } + ) + seen.add(signature) + added += 1 + return added +def _update_meta(db: dict[str, Any]) -> None: + meta = db.setdefault("meta", {}) + meta.setdefault("schema_version", "2.0") + meta["last_updated"] = datetime.now(timezone.utc).isoformat(timespec="seconds").replace("+00:00", "Z") + weeks_covered = sorted( + { + int(item.get("week")) + for item in _safe_list(db.get("weeks")) + if isinstance(item, dict) and str(item.get("week", "")).isdigit() + } + ) + meta["weeks_covered"] = weeks_covered + sources = [source for source in _safe_list(meta.get("sources")) if isinstance(source, str)] + seen = {source.lower() for source in sources} + for week in _safe_list(db.get("weeks")): + if not isinstance(week, dict): + continue + for source in _safe_list(week.get("sources")): + if not isinstance(source, str): + continue + key = source.lower() + if key in seen: + continue + sources.append(source) + seen.add(key) + for exam in _safe_list(db.get("assessments", {}).get("exams")): + if not isinstance(exam, dict): + continue + source = exam.get("source") + if not isinstance(source, str): + continue + key = source.lower() + if key in seen: + continue + sources.append(source) + seen.add(key) + meta["sources"] = sources +def integrate_homework_into_study_db( + *, + db: dict[str, Any], + homework_dir: Path, +) -> dict[str, Any]: + candidates, week_sources = build_candidates(homework_dir) + by_week: dict[int, list[CandidateCell]] = {} + for candidate in candidates: + by_week.setdefault(candidate.week, []).append(candidate) + week_index = _index_weeks(db) + report: dict[str, Any] = { + "timestamp_utc": datetime.now(timezone.utc).isoformat(timespec="seconds").replace("+00:00", "Z"), + "homework_dir": str(homework_dir), + "weeks": [], + "summary": { + "total_candidate_homework_cells": len(candidates), + "total_added_homework_cells": 0, + "total_added_sources": 0, + }, + } + for week in sorted(set(list(week_sources.keys()) + list(by_week.keys()))): + week_rec = week_index.get(week) + if not week_rec: + report["weeks"].append( + { + "week": week, + "status": "missing_week_in_study_db", + "candidate_homework_cells": len(by_week.get(week, [])), + "added_homework_cells": 0, + "added_sources": 0, + } + ) + continue + added_sources = _append_unique_sources(week_rec, week_sources.get(week, [])) + added_homework = _append_unique_homework_cells(week_rec, by_week.get(week, [])) + report["summary"]["total_added_homework_cells"] += added_homework + report["summary"]["total_added_sources"] += added_sources + report["weeks"].append( + { + "week": week, + "status": "updated", + "candidate_homework_cells": len(by_week.get(week, [])), + "added_homework_cells": added_homework, + "added_sources": added_sources, + "total_week_sources": len(_safe_list(week_rec.get("sources"))), + "total_week_homework_cells": len(_safe_list(week_rec.get("homework_cells"))), + } + ) + _update_meta(db) + knowledge = db.setdefault("knowledge", {}) + knowledge["topic_analysis"] = recompute_topic_analysis(flatten_study_db_for_pipeline(db)) + return report +def sync_topic_cards_homework( + *, + db: dict[str, Any], + topic_cards_path: Path, +) -> dict[str, Any]: + payload = json.loads(topic_cards_path.read_text(encoding="utf-8")) + cards = [card for card in _safe_list(payload.get("cards")) if isinstance(card, dict)] + materialized = flatten_study_db_for_pipeline(db) + homeworks = [cell for cell in _safe_list(materialized.get("homeworks")) if isinstance(cell, dict)] + added_total = 0 + by_card_counts: dict[str, int] = {} + for card in cards: + sections = card.setdefault("sections", {}) + sections["homework_snippets"] = [] + card_id = str(card.get("id") or "").strip() + canonical = topic_key(str(card.get("canonical_topic") or card.get("topic") or "")) + snippets: list[dict[str, Any]] = [] + for cell in homeworks: + if cell.get("is_advanced_optional"): + continue + topic = str(cell.get("topic") or "") + if not topic: + continue + source_key = topic_key(topic) + explicit_targets = HOMEWORK_CARD_TARGETS.get(source_key, ()) + if explicit_targets: + if card_id not in explicit_targets: + continue + elif not is_relevant(canonical, source_key, threshold=0.6): + continue + cleaned_source = clean_notebook_source(str(cell.get("source") or ""), str(cell.get("cell_type") or "code")) + if not cleaned_source: + continue + snippet = { + "id": make_id("hw", f"{cell.get('week')}-{cell.get('cell_index')}-{topic}"), + "week": cell.get("week"), + "cell_index": cell.get("cell_index"), + "cell_type": cell.get("cell_type"), + "topic": topic, + "source": cleaned_source, + "outputs": [compact_text(out, 400) for out in (cell.get("outputs") or [])[:2] if out and str(out).strip()], + "source_origin": cell.get("source_origin", ""), + } + snippets.append(snippet) + deduped = dedupe_list(snippets, ["id"])[:12] + sections["homework_snippets"] = deduped + recommended_count = min(4, max(1, (len(deduped) + 1) // 2)) if deduped else 0 + sections["homework_recommended_ids"] = [snippet.get("id") for snippet in deduped[:recommended_count] if snippet.get("id")] + by_card_counts[str(card.get("id") or "")] = len(deduped) + added_total += len(deduped) + payload["cards"] = cards + topic_cards_path.write_text(json.dumps(payload, ensure_ascii=False, indent=2), encoding="utf-8") + cards_with_homework = len([count for count in by_card_counts.values() if count > 0]) + return { + "cards_total": len(cards), + "cards_with_homework_snippets": cards_with_homework, + "total_homework_snippets_attached": added_total, + } +def main() -> None: + args = parse_args() + homework_dir = args.homework_dir.resolve() + if not homework_dir.exists() or not homework_dir.is_dir(): + raise FileNotFoundError(f"Homework directory not found or not a directory: {homework_dir}") + if not args.topic_cards.exists(): + raise FileNotFoundError(f"topic_cards file not found: {args.topic_cards}") + db = load_study_db(args.study_db) + db_before = json.loads(json.dumps(db)) + cards_before = args.topic_cards.read_text(encoding="utf-8") + db_report = integrate_homework_into_study_db(db=db, homework_dir=homework_dir) + if args.dry_run: + cards_report = sync_topic_cards_homework(db=db, topic_cards_path=args.topic_cards) + args.topic_cards.write_text(cards_before, encoding="utf-8") + db = db_before + else: + write_study_db(db, args.study_db) + cards_report = sync_topic_cards_homework(db=db, topic_cards_path=args.topic_cards) + report = { + "timestamp_utc": datetime.now(timezone.utc).isoformat(timespec="seconds").replace("+00:00", "Z"), + "dry_run": bool(args.dry_run), + "study_db": str(args.study_db), + "topic_cards": str(args.topic_cards), + "homework_dir": str(homework_dir), + "study_db_integration": db_report, + "topic_cards_sync": cards_report, + } + args.report_file.parent.mkdir(parents=True, exist_ok=True) + args.report_file.write_text(json.dumps(report, ensure_ascii=False, indent=2), encoding="utf-8") + print( + ("Dry-run completed:" if args.dry_run else "Homework integration completed:"), + f"added_homework_cells={db_report['summary']['total_added_homework_cells']}", + f"added_sources={db_report['summary']['total_added_sources']}", + f"cards_with_homework={cards_report['cards_with_homework_snippets']}", + f"report={args.report_file}", + ) +if __name__ == "__main__": + main() diff --git a/tests/test_exam_coverage_audit.py b/tests/test_exam_coverage_audit.py new file mode 100644 index 0000000..ce124f8 --- /dev/null +++ b/tests/test_exam_coverage_audit.py @@ -0,0 +1,88 @@ +from pathlib import Path +import unittest + +from scripts.exam_coverage_audit import EXAM_SOURCES, ROOT, iter_selectable_items, portable_path, unique_exam_sources + + +class ExamCoverageAuditTests(unittest.TestCase): + def test_iter_selectable_items_excludes_ai_summary_and_keeps_detail_ids(self) -> None: + cards = [ + { + "id": "card-1", + "topic": "Demo Topic", + "sections": { + "ai_summary": {"content": "Useful but not selectable."}, + "ai_common_questions": {"items": [{"id": "aiq-1", "summary": "What is x?"}]}, + "key_points_to_remember": [ + { + "id": "kp-1", + "text": "Names bind to objects.", + "details": [{"id": "kp-1-d1", "title": "Example", "code": "x = 1"}], + } + ], + "ai_examples": [{"id": "ai-example-1", "title": "Demo", "code": "print(1)"}], + "exam_questions": [{"id": "exam-1", "question": "What prints?"}], + "lecture_snippets": [{"id": "lecture-1", "explanation": "Names can be rebound.", "code_examples": []}], + "notebook_snippets": [{"id": "nb-1", "source": "values = [1, 2]\\nprint(values)", "outputs": ["[1, 2]"]}], + "recommended_ids": ["exam-1", "lecture-1"], + }, + } + ] + + items = iter_selectable_items(cards) + item_ids = {item["item_id"] for item in items} + item_types = {item["item_type"] for item in items} + + self.assertIn("aiq-1", item_ids) + self.assertIn("kp-1", item_ids) + self.assertIn("kp-1-d1", item_ids) + self.assertIn("ai-example-1", item_ids) + self.assertIn("exam-1", item_ids) + self.assertIn("lecture-1", item_ids) + self.assertIn("nb-1", item_ids) + self.assertNotIn("ai_summary", item_types) + + def test_recommended_and_additional_source_buckets_match_ui_split(self) -> None: + cards = [ + { + "id": "card-1", + "topic": "Demo Topic", + "sections": { + "ai_summary": {}, + "ai_common_questions": {}, + "key_points_to_remember": [], + "ai_examples": [], + "exam_questions": [{"id": "exam-1", "question": "Q"}], + "lecture_snippets": [{"id": "lecture-1", "explanation": "Long enough explanation.", "code_examples": []}], + "notebook_snippets": [{"id": "nb-1", "source": "x = 1\\nprint(x)", "outputs": ["1"]}], + "recommended_ids": ["lecture-1"], + }, + } + ] + + items = {item["item_id"]: item for item in iter_selectable_items(cards)} + self.assertEqual(items["lecture-1"]["bucket"], "recommended") + self.assertEqual(items["exam-1"]["bucket"], "additional") + self.assertEqual(items["nb-1"]["bucket"], "additional") + + def test_unique_exam_sources_drop_the_known_duplicate_copy(self) -> None: + duplicate_exam_ids = {exam["exam_id"] for exam in EXAM_SOURCES if exam.get("duplicate_of")} + unique_exam_ids = {exam["exam_id"] for exam in unique_exam_sources()} + + self.assertEqual(len(duplicate_exam_ids), 1) + self.assertEqual(len(unique_exam_ids), len(EXAM_SOURCES) - 1) + self.assertFalse(duplicate_exam_ids & unique_exam_ids) + + def test_portable_path_strips_machine_specific_prefixes(self) -> None: + repo_file = ROOT / "topic_cards.json" + sibling_file = ROOT.parent / "course_files_after_midterm" / "Sample Final plus answers.pdf" + + self.assertEqual(portable_path(repo_file), "topic_cards.json") + self.assertEqual( + portable_path(sibling_file), + Path("..", "course_files_after_midterm", "Sample Final plus answers.pdf").as_posix(), + ) + + +if __name__ == "__main__": + unittest.main() diff --git a/tests/test_integrate_homework_material_script.py b/tests/test_integrate_homework_material_script.py new file mode 100644 index 0000000..3810cf8 --- /dev/null +++ b/tests/test_integrate_homework_material_script.py @@ -0,0 +1,53 @@ +import hashlib +import json +from pathlib import Path +import subprocess +import sys +import tempfile +import unittest + + +class IntegrateHomeworkMaterialScriptTests(unittest.TestCase): + @classmethod + def setUpClass(cls) -> None: + cls.root = Path(__file__).resolve().parents[1] + cls.script = cls.root / "scripts" / "integrate_homework_material.py" + cls.study_db = cls.root / "data" / "study_db.json" + cls.topic_cards = cls.root / "topic_cards.json" + + @staticmethod + def _digest(path: Path) -> str: + return hashlib.sha256(path.read_bytes()).hexdigest() + + def _run(self, args: list[str]) -> subprocess.CompletedProcess[str]: + return subprocess.run( + [sys.executable, str(self.script), *args], + cwd=self.root, + capture_output=True, + text=True, + ) + + def test_dry_run_does_not_modify_data_files(self) -> None: + before_db = self._digest(self.study_db) + before_cards = self._digest(self.topic_cards) + + with tempfile.TemporaryDirectory() as tmp: + report_path = Path(tmp) / "report.json" + result = self._run(["--dry-run", "--report-file", str(report_path)]) + + self.assertEqual(0, result.returncode, msg=f"stdout:\n{result.stdout}\nstderr:\n{result.stderr}") + self.assertTrue(report_path.exists(), "Expected dry-run report file to be written.") + + after_db = self._digest(self.study_db) + after_cards = self._digest(self.topic_cards) + self.assertEqual(before_db, after_db, "Dry-run unexpectedly modified data/study_db.json") + self.assertEqual(before_cards, after_cards, "Dry-run unexpectedly modified topic_cards.json") + + report = json.loads(report_path.read_text(encoding="utf-8")) + self.assertTrue(report.get("dry_run")) + summary = report.get("study_db_integration", {}).get("summary", {}) + self.assertGreaterEqual(summary.get("total_candidate_homework_cells", 0), 1) + + +if __name__ == "__main__": + unittest.main() diff --git a/tests/test_shared_study_database.py b/tests/test_shared_study_database.py index 14c1da1..7fa67ad 100644 --- a/tests/test_shared_study_database.py +++ b/tests/test_shared_study_database.py @@ -69,6 +69,35 @@ def test_flatten_v3_preserves_week_local_notebook_cell_indexes(self) -> None: self.assertEqual([8, 2], [item["cell_index"] for item in materialized["notebooks"]]) + def test_flatten_v3_includes_explicit_homework_cells(self) -> None: + db = { + "meta": {"schema_version": "3.0"}, + "weeks": [ + { + "week": 2, + "topics": [], + "homework_cells": [ + { + "cell_index": 3, + "cell_type": "code", + "topic": "conditions", + "source": "print('homework')", + "outputs": [], + "source_origin": "materials/homework/week 2/Exercise_2.8.py", + } + ], + } + ], + "assessments": {"exams": []}, + "knowledge": {}, + } + + materialized = flatten_study_db_for_pipeline(db) + + self.assertEqual(1, len(materialized["homeworks"])) + self.assertEqual(2, materialized["homeworks"][0]["week"]) + self.assertEqual("conditions", materialized["homeworks"][0]["topic"]) + if __name__ == "__main__": unittest.main() diff --git a/tests/test_topic_cards_integrity.py b/tests/test_topic_cards_integrity.py index 82ff75e..7ee0eed 100644 --- a/tests/test_topic_cards_integrity.py +++ b/tests/test_topic_cards_integrity.py @@ -1,7 +1,5 @@ import json -from collections import Counter from pathlib import Path -import re import unittest @@ -39,14 +37,7 @@ def test_cards_have_expected_shape(self) -> None: self.assertIsInstance(card.get("trap_patterns"), list) sections = card["sections"] - for key in [ - "lecture_snippets", - "exam_questions", - "notebook_snippets", - "ai_examples", - "key_points_to_remember", - "recommended_ids", - ]: + for key in ["lecture_snippets", "exam_questions", "notebook_snippets", "ai_examples", "key_points_to_remember", "recommended_ids"]: self.assertIsInstance(sections.get(key), list, f"{card['id']}: {key} must be list") self.assertIsInstance(sections.get("ai_summary"), dict, f"{card['id']}: ai_summary must be dict") self.assertIsInstance(sections.get("ai_common_questions"), dict, f"{card['id']}: ai_common_questions must be dict") @@ -94,6 +85,19 @@ def test_subtopic_item_ids_reference_real_items(self) -> None: for item_id in bucket_ids: self.assertIn(item_id, valid_ids, f"{card['id']}: unknown subtopic item id {item_id}") + def test_curated_homework_promotions_keep_outputs(self) -> None: + promoted_count = 0 + for card in self.cards: + for snippet in card.get("sections", {}).get("notebook_snippets", []): + snippet_id = str(snippet.get("id") or "") + if not snippet_id.startswith("cs-curated-hw-"): + continue + promoted_count += 1 + self.assertEqual(snippet.get("source_type"), "notebook", f"{card['id']}: {snippet_id} must stay UI-visible") + self.assertTrue(snippet.get("outputs"), f"{card['id']}: {snippet_id} should include concrete output") + self.assertTrue(str(snippet.get("title") or "").strip(), f"{card['id']}: {snippet_id} should have a descriptive title") + self.assertGreater(promoted_count, 0, "Expected at least one curated homework promotion in notebook_snippets") + def test_common_question_bullets_are_unique_per_card(self) -> None: for card in self.cards: bullets = card.get("sections", {}).get("ai_common_questions", {}).get("bullets", []) @@ -134,7 +138,5 @@ def _table_signature(table: dict | None) -> str: for row in table.get("rows", []) ) return f"{headers}###{rows}" - - if __name__ == "__main__": unittest.main() diff --git a/tmp/exam_coverage_audit/manifest.json b/tmp/exam_coverage_audit/manifest.json new file mode 100644 index 0000000..45d929f --- /dev/null +++ b/tmp/exam_coverage_audit/manifest.json @@ -0,0 +1,205 @@ +{ + "topic_cards_path": "/Users/juliuseikmans/Desktop/Studies/2025-2026/intro to python/python-exam-cheat-sheet-generator/topic_cards.json", + "selectable_items_path": "/Users/juliuseikmans/Desktop/Studies/2025-2026/intro to python/python-exam-cheat-sheet-generator/tmp/exam_coverage_audit/selectable_items.json", + "current_repo_cards": 27, + "unique_exam_count": 7, + "excluded_duplicates": [ + { + "exam_id": "final-exam-solutions-for-python-programming-course-code-308088-308234", + "duplicate_of": "final-exam-solutions-for-python-programming-62oop21", + "pdf_path": "/Users/juliuseikmans/Desktop/Studies/2025-2026/intro to python/course_files_after_midterm/practice_exams_previous_years/final-exam-solutions-for-python-programming-course-code-308088-308234.pdf" + } + ], + "exams": [ + { + "exam_id": "sample-final-plus-answers", + "title": "2025 Sample Final Plus Answers", + "pdf_path": "/Users/juliuseikmans/Desktop/Studies/2025-2026/intro to python/course_files_after_midterm/Sample Final plus answers.pdf", + "expected_questions": 24, + "page_count": 31, + "page_image_paths": [ + "/Users/juliuseikmans/Desktop/Studies/2025-2026/intro to python/python-exam-cheat-sheet-generator/tmp/exam_coverage_audit/pages/sample-final-plus-answers/page-01.png", + "/Users/juliuseikmans/Desktop/Studies/2025-2026/intro to python/python-exam-cheat-sheet-generator/tmp/exam_coverage_audit/pages/sample-final-plus-answers/page-02.png", + "/Users/juliuseikmans/Desktop/Studies/2025-2026/intro to python/python-exam-cheat-sheet-generator/tmp/exam_coverage_audit/pages/sample-final-plus-answers/page-03.png", + "/Users/juliuseikmans/Desktop/Studies/2025-2026/intro to python/python-exam-cheat-sheet-generator/tmp/exam_coverage_audit/pages/sample-final-plus-answers/page-04.png", + "/Users/juliuseikmans/Desktop/Studies/2025-2026/intro to python/python-exam-cheat-sheet-generator/tmp/exam_coverage_audit/pages/sample-final-plus-answers/page-05.png", + "/Users/juliuseikmans/Desktop/Studies/2025-2026/intro to python/python-exam-cheat-sheet-generator/tmp/exam_coverage_audit/pages/sample-final-plus-answers/page-06.png", + "/Users/juliuseikmans/Desktop/Studies/2025-2026/intro to python/python-exam-cheat-sheet-generator/tmp/exam_coverage_audit/pages/sample-final-plus-answers/page-07.png", + "/Users/juliuseikmans/Desktop/Studies/2025-2026/intro to python/python-exam-cheat-sheet-generator/tmp/exam_coverage_audit/pages/sample-final-plus-answers/page-08.png", + "/Users/juliuseikmans/Desktop/Studies/2025-2026/intro to python/python-exam-cheat-sheet-generator/tmp/exam_coverage_audit/pages/sample-final-plus-answers/page-09.png", + "/Users/juliuseikmans/Desktop/Studies/2025-2026/intro to python/python-exam-cheat-sheet-generator/tmp/exam_coverage_audit/pages/sample-final-plus-answers/page-10.png", + "/Users/juliuseikmans/Desktop/Studies/2025-2026/intro to python/python-exam-cheat-sheet-generator/tmp/exam_coverage_audit/pages/sample-final-plus-answers/page-11.png", + "/Users/juliuseikmans/Desktop/Studies/2025-2026/intro to python/python-exam-cheat-sheet-generator/tmp/exam_coverage_audit/pages/sample-final-plus-answers/page-12.png", + "/Users/juliuseikmans/Desktop/Studies/2025-2026/intro to python/python-exam-cheat-sheet-generator/tmp/exam_coverage_audit/pages/sample-final-plus-answers/page-13.png", + "/Users/juliuseikmans/Desktop/Studies/2025-2026/intro to python/python-exam-cheat-sheet-generator/tmp/exam_coverage_audit/pages/sample-final-plus-answers/page-14.png", + "/Users/juliuseikmans/Desktop/Studies/2025-2026/intro to python/python-exam-cheat-sheet-generator/tmp/exam_coverage_audit/pages/sample-final-plus-answers/page-15.png", + "/Users/juliuseikmans/Desktop/Studies/2025-2026/intro to python/python-exam-cheat-sheet-generator/tmp/exam_coverage_audit/pages/sample-final-plus-answers/page-16.png", + "/Users/juliuseikmans/Desktop/Studies/2025-2026/intro to python/python-exam-cheat-sheet-generator/tmp/exam_coverage_audit/pages/sample-final-plus-answers/page-17.png", + "/Users/juliuseikmans/Desktop/Studies/2025-2026/intro to python/python-exam-cheat-sheet-generator/tmp/exam_coverage_audit/pages/sample-final-plus-answers/page-18.png", + "/Users/juliuseikmans/Desktop/Studies/2025-2026/intro to python/python-exam-cheat-sheet-generator/tmp/exam_coverage_audit/pages/sample-final-plus-answers/page-19.png", + "/Users/juliuseikmans/Desktop/Studies/2025-2026/intro to python/python-exam-cheat-sheet-generator/tmp/exam_coverage_audit/pages/sample-final-plus-answers/page-20.png", + "/Users/juliuseikmans/Desktop/Studies/2025-2026/intro to python/python-exam-cheat-sheet-generator/tmp/exam_coverage_audit/pages/sample-final-plus-answers/page-21.png", + "/Users/juliuseikmans/Desktop/Studies/2025-2026/intro to python/python-exam-cheat-sheet-generator/tmp/exam_coverage_audit/pages/sample-final-plus-answers/page-22.png", + "/Users/juliuseikmans/Desktop/Studies/2025-2026/intro to python/python-exam-cheat-sheet-generator/tmp/exam_coverage_audit/pages/sample-final-plus-answers/page-23.png", + "/Users/juliuseikmans/Desktop/Studies/2025-2026/intro to python/python-exam-cheat-sheet-generator/tmp/exam_coverage_audit/pages/sample-final-plus-answers/page-24.png", + "/Users/juliuseikmans/Desktop/Studies/2025-2026/intro to python/python-exam-cheat-sheet-generator/tmp/exam_coverage_audit/pages/sample-final-plus-answers/page-25.png", + "/Users/juliuseikmans/Desktop/Studies/2025-2026/intro to python/python-exam-cheat-sheet-generator/tmp/exam_coverage_audit/pages/sample-final-plus-answers/page-26.png", + "/Users/juliuseikmans/Desktop/Studies/2025-2026/intro to python/python-exam-cheat-sheet-generator/tmp/exam_coverage_audit/pages/sample-final-plus-answers/page-27.png", + "/Users/juliuseikmans/Desktop/Studies/2025-2026/intro to python/python-exam-cheat-sheet-generator/tmp/exam_coverage_audit/pages/sample-final-plus-answers/page-28.png", + "/Users/juliuseikmans/Desktop/Studies/2025-2026/intro to python/python-exam-cheat-sheet-generator/tmp/exam_coverage_audit/pages/sample-final-plus-answers/page-29.png", + "/Users/juliuseikmans/Desktop/Studies/2025-2026/intro to python/python-exam-cheat-sheet-generator/tmp/exam_coverage_audit/pages/sample-final-plus-answers/page-30.png", + "/Users/juliuseikmans/Desktop/Studies/2025-2026/intro to python/python-exam-cheat-sheet-generator/tmp/exam_coverage_audit/pages/sample-final-plus-answers/page-31.png" + ] + }, + { + "exam_id": "final-exam-solutions-for-python-programming-62oop21", + "title": "2022 Final Exam", + "pdf_path": "/Users/juliuseikmans/Desktop/Studies/2025-2026/intro to python/course_files_after_midterm/practice_exams_previous_years/final-exam-solutions-for-python-programming-62oop21.pdf", + "expected_questions": 24, + "page_count": 15, + "page_image_paths": [ + "/Users/juliuseikmans/Desktop/Studies/2025-2026/intro to python/python-exam-cheat-sheet-generator/tmp/exam_coverage_audit/pages/final-exam-solutions-for-python-programming-62oop21/page-01.png", + "/Users/juliuseikmans/Desktop/Studies/2025-2026/intro to python/python-exam-cheat-sheet-generator/tmp/exam_coverage_audit/pages/final-exam-solutions-for-python-programming-62oop21/page-02.png", + "/Users/juliuseikmans/Desktop/Studies/2025-2026/intro to python/python-exam-cheat-sheet-generator/tmp/exam_coverage_audit/pages/final-exam-solutions-for-python-programming-62oop21/page-03.png", + "/Users/juliuseikmans/Desktop/Studies/2025-2026/intro to python/python-exam-cheat-sheet-generator/tmp/exam_coverage_audit/pages/final-exam-solutions-for-python-programming-62oop21/page-04.png", + "/Users/juliuseikmans/Desktop/Studies/2025-2026/intro to python/python-exam-cheat-sheet-generator/tmp/exam_coverage_audit/pages/final-exam-solutions-for-python-programming-62oop21/page-05.png", + "/Users/juliuseikmans/Desktop/Studies/2025-2026/intro to python/python-exam-cheat-sheet-generator/tmp/exam_coverage_audit/pages/final-exam-solutions-for-python-programming-62oop21/page-06.png", + "/Users/juliuseikmans/Desktop/Studies/2025-2026/intro to python/python-exam-cheat-sheet-generator/tmp/exam_coverage_audit/pages/final-exam-solutions-for-python-programming-62oop21/page-07.png", + "/Users/juliuseikmans/Desktop/Studies/2025-2026/intro to python/python-exam-cheat-sheet-generator/tmp/exam_coverage_audit/pages/final-exam-solutions-for-python-programming-62oop21/page-08.png", + "/Users/juliuseikmans/Desktop/Studies/2025-2026/intro to python/python-exam-cheat-sheet-generator/tmp/exam_coverage_audit/pages/final-exam-solutions-for-python-programming-62oop21/page-09.png", + "/Users/juliuseikmans/Desktop/Studies/2025-2026/intro to python/python-exam-cheat-sheet-generator/tmp/exam_coverage_audit/pages/final-exam-solutions-for-python-programming-62oop21/page-10.png", + "/Users/juliuseikmans/Desktop/Studies/2025-2026/intro to python/python-exam-cheat-sheet-generator/tmp/exam_coverage_audit/pages/final-exam-solutions-for-python-programming-62oop21/page-11.png", + "/Users/juliuseikmans/Desktop/Studies/2025-2026/intro to python/python-exam-cheat-sheet-generator/tmp/exam_coverage_audit/pages/final-exam-solutions-for-python-programming-62oop21/page-12.png", + "/Users/juliuseikmans/Desktop/Studies/2025-2026/intro to python/python-exam-cheat-sheet-generator/tmp/exam_coverage_audit/pages/final-exam-solutions-for-python-programming-62oop21/page-13.png", + "/Users/juliuseikmans/Desktop/Studies/2025-2026/intro to python/python-exam-cheat-sheet-generator/tmp/exam_coverage_audit/pages/final-exam-solutions-for-python-programming-62oop21/page-14.png", + "/Users/juliuseikmans/Desktop/Studies/2025-2026/intro to python/python-exam-cheat-sheet-generator/tmp/exam_coverage_audit/pages/final-exam-solutions-for-python-programming-62oop21/page-15.png" + ] + }, + { + "exam_id": "final-exam-study-guide-trial-python-basics-2023", + "title": "2023 Trial Final Study Guide", + "pdf_path": "/Users/juliuseikmans/Desktop/Studies/2025-2026/intro to python/course_files_after_midterm/practice_exams_previous_years/final-exam-study-guide-trial-python-basics-2023.pdf", + "expected_questions": 24, + "page_count": 17, + "page_image_paths": [ + "/Users/juliuseikmans/Desktop/Studies/2025-2026/intro to python/python-exam-cheat-sheet-generator/tmp/exam_coverage_audit/pages/final-exam-study-guide-trial-python-basics-2023/page-01.png", + "/Users/juliuseikmans/Desktop/Studies/2025-2026/intro to python/python-exam-cheat-sheet-generator/tmp/exam_coverage_audit/pages/final-exam-study-guide-trial-python-basics-2023/page-02.png", + "/Users/juliuseikmans/Desktop/Studies/2025-2026/intro to python/python-exam-cheat-sheet-generator/tmp/exam_coverage_audit/pages/final-exam-study-guide-trial-python-basics-2023/page-03.png", + "/Users/juliuseikmans/Desktop/Studies/2025-2026/intro to python/python-exam-cheat-sheet-generator/tmp/exam_coverage_audit/pages/final-exam-study-guide-trial-python-basics-2023/page-04.png", + "/Users/juliuseikmans/Desktop/Studies/2025-2026/intro to python/python-exam-cheat-sheet-generator/tmp/exam_coverage_audit/pages/final-exam-study-guide-trial-python-basics-2023/page-05.png", + "/Users/juliuseikmans/Desktop/Studies/2025-2026/intro to python/python-exam-cheat-sheet-generator/tmp/exam_coverage_audit/pages/final-exam-study-guide-trial-python-basics-2023/page-06.png", + "/Users/juliuseikmans/Desktop/Studies/2025-2026/intro to python/python-exam-cheat-sheet-generator/tmp/exam_coverage_audit/pages/final-exam-study-guide-trial-python-basics-2023/page-07.png", + "/Users/juliuseikmans/Desktop/Studies/2025-2026/intro to python/python-exam-cheat-sheet-generator/tmp/exam_coverage_audit/pages/final-exam-study-guide-trial-python-basics-2023/page-08.png", + "/Users/juliuseikmans/Desktop/Studies/2025-2026/intro to python/python-exam-cheat-sheet-generator/tmp/exam_coverage_audit/pages/final-exam-study-guide-trial-python-basics-2023/page-09.png", + "/Users/juliuseikmans/Desktop/Studies/2025-2026/intro to python/python-exam-cheat-sheet-generator/tmp/exam_coverage_audit/pages/final-exam-study-guide-trial-python-basics-2023/page-10.png", + "/Users/juliuseikmans/Desktop/Studies/2025-2026/intro to python/python-exam-cheat-sheet-generator/tmp/exam_coverage_audit/pages/final-exam-study-guide-trial-python-basics-2023/page-11.png", + "/Users/juliuseikmans/Desktop/Studies/2025-2026/intro to python/python-exam-cheat-sheet-generator/tmp/exam_coverage_audit/pages/final-exam-study-guide-trial-python-basics-2023/page-12.png", + "/Users/juliuseikmans/Desktop/Studies/2025-2026/intro to python/python-exam-cheat-sheet-generator/tmp/exam_coverage_audit/pages/final-exam-study-guide-trial-python-basics-2023/page-13.png", + "/Users/juliuseikmans/Desktop/Studies/2025-2026/intro to python/python-exam-cheat-sheet-generator/tmp/exam_coverage_audit/pages/final-exam-study-guide-trial-python-basics-2023/page-14.png", + "/Users/juliuseikmans/Desktop/Studies/2025-2026/intro to python/python-exam-cheat-sheet-generator/tmp/exam_coverage_audit/pages/final-exam-study-guide-trial-python-basics-2023/page-15.png", + "/Users/juliuseikmans/Desktop/Studies/2025-2026/intro to python/python-exam-cheat-sheet-generator/tmp/exam_coverage_audit/pages/final-exam-study-guide-trial-python-basics-2023/page-16.png", + "/Users/juliuseikmans/Desktop/Studies/2025-2026/intro to python/python-exam-cheat-sheet-generator/tmp/exam_coverage_audit/pages/final-exam-study-guide-trial-python-basics-2023/page-17.png" + ] + }, + { + "exam_id": "introduction-to-python-trial-final-exam-solutions-py22", + "title": "2024 Trial Final", + "pdf_path": "/Users/juliuseikmans/Desktop/Studies/2025-2026/intro to python/course_files_after_midterm/practice_exams_previous_years/introduction-to-python-trial-final-exam-solutions-py22.pdf", + "expected_questions": 24, + "page_count": 17, + "page_image_paths": [ + "/Users/juliuseikmans/Desktop/Studies/2025-2026/intro to python/python-exam-cheat-sheet-generator/tmp/exam_coverage_audit/pages/introduction-to-python-trial-final-exam-solutions-py22/page-01.png", + "/Users/juliuseikmans/Desktop/Studies/2025-2026/intro to python/python-exam-cheat-sheet-generator/tmp/exam_coverage_audit/pages/introduction-to-python-trial-final-exam-solutions-py22/page-02.png", + "/Users/juliuseikmans/Desktop/Studies/2025-2026/intro to python/python-exam-cheat-sheet-generator/tmp/exam_coverage_audit/pages/introduction-to-python-trial-final-exam-solutions-py22/page-03.png", + "/Users/juliuseikmans/Desktop/Studies/2025-2026/intro to python/python-exam-cheat-sheet-generator/tmp/exam_coverage_audit/pages/introduction-to-python-trial-final-exam-solutions-py22/page-04.png", + "/Users/juliuseikmans/Desktop/Studies/2025-2026/intro to python/python-exam-cheat-sheet-generator/tmp/exam_coverage_audit/pages/introduction-to-python-trial-final-exam-solutions-py22/page-05.png", + "/Users/juliuseikmans/Desktop/Studies/2025-2026/intro to python/python-exam-cheat-sheet-generator/tmp/exam_coverage_audit/pages/introduction-to-python-trial-final-exam-solutions-py22/page-06.png", + "/Users/juliuseikmans/Desktop/Studies/2025-2026/intro to python/python-exam-cheat-sheet-generator/tmp/exam_coverage_audit/pages/introduction-to-python-trial-final-exam-solutions-py22/page-07.png", + "/Users/juliuseikmans/Desktop/Studies/2025-2026/intro to python/python-exam-cheat-sheet-generator/tmp/exam_coverage_audit/pages/introduction-to-python-trial-final-exam-solutions-py22/page-08.png", + "/Users/juliuseikmans/Desktop/Studies/2025-2026/intro to python/python-exam-cheat-sheet-generator/tmp/exam_coverage_audit/pages/introduction-to-python-trial-final-exam-solutions-py22/page-09.png", + "/Users/juliuseikmans/Desktop/Studies/2025-2026/intro to python/python-exam-cheat-sheet-generator/tmp/exam_coverage_audit/pages/introduction-to-python-trial-final-exam-solutions-py22/page-10.png", + "/Users/juliuseikmans/Desktop/Studies/2025-2026/intro to python/python-exam-cheat-sheet-generator/tmp/exam_coverage_audit/pages/introduction-to-python-trial-final-exam-solutions-py22/page-11.png", + "/Users/juliuseikmans/Desktop/Studies/2025-2026/intro to python/python-exam-cheat-sheet-generator/tmp/exam_coverage_audit/pages/introduction-to-python-trial-final-exam-solutions-py22/page-12.png", + "/Users/juliuseikmans/Desktop/Studies/2025-2026/intro to python/python-exam-cheat-sheet-generator/tmp/exam_coverage_audit/pages/introduction-to-python-trial-final-exam-solutions-py22/page-13.png", + "/Users/juliuseikmans/Desktop/Studies/2025-2026/intro to python/python-exam-cheat-sheet-generator/tmp/exam_coverage_audit/pages/introduction-to-python-trial-final-exam-solutions-py22/page-14.png", + "/Users/juliuseikmans/Desktop/Studies/2025-2026/intro to python/python-exam-cheat-sheet-generator/tmp/exam_coverage_audit/pages/introduction-to-python-trial-final-exam-solutions-py22/page-15.png", + "/Users/juliuseikmans/Desktop/Studies/2025-2026/intro to python/python-exam-cheat-sheet-generator/tmp/exam_coverage_audit/pages/introduction-to-python-trial-final-exam-solutions-py22/page-16.png", + "/Users/juliuseikmans/Desktop/Studies/2025-2026/intro to python/python-exam-cheat-sheet-generator/tmp/exam_coverage_audit/pages/introduction-to-python-trial-final-exam-solutions-py22/page-17.png" + ] + }, + { + "exam_id": "resit-exam-guidelines-for-intro-to-python-6013b0470y-july-2023", + "title": "2023 Resit Exam Guidelines", + "pdf_path": "/Users/juliuseikmans/Desktop/Studies/2025-2026/intro to python/course_files_after_midterm/practice_exams_previous_years/resit-exam-guidelines-for-intro-to-python-6013b0470y-july-2023.pdf", + "expected_questions": 24, + "page_count": 17, + "page_image_paths": [ + "/Users/juliuseikmans/Desktop/Studies/2025-2026/intro to python/python-exam-cheat-sheet-generator/tmp/exam_coverage_audit/pages/resit-exam-guidelines-for-intro-to-python-6013b0470y-july-2023/page-01.png", + "/Users/juliuseikmans/Desktop/Studies/2025-2026/intro to python/python-exam-cheat-sheet-generator/tmp/exam_coverage_audit/pages/resit-exam-guidelines-for-intro-to-python-6013b0470y-july-2023/page-02.png", + "/Users/juliuseikmans/Desktop/Studies/2025-2026/intro to python/python-exam-cheat-sheet-generator/tmp/exam_coverage_audit/pages/resit-exam-guidelines-for-intro-to-python-6013b0470y-july-2023/page-03.png", + "/Users/juliuseikmans/Desktop/Studies/2025-2026/intro to python/python-exam-cheat-sheet-generator/tmp/exam_coverage_audit/pages/resit-exam-guidelines-for-intro-to-python-6013b0470y-july-2023/page-04.png", + "/Users/juliuseikmans/Desktop/Studies/2025-2026/intro to python/python-exam-cheat-sheet-generator/tmp/exam_coverage_audit/pages/resit-exam-guidelines-for-intro-to-python-6013b0470y-july-2023/page-05.png", + "/Users/juliuseikmans/Desktop/Studies/2025-2026/intro to python/python-exam-cheat-sheet-generator/tmp/exam_coverage_audit/pages/resit-exam-guidelines-for-intro-to-python-6013b0470y-july-2023/page-06.png", + "/Users/juliuseikmans/Desktop/Studies/2025-2026/intro to python/python-exam-cheat-sheet-generator/tmp/exam_coverage_audit/pages/resit-exam-guidelines-for-intro-to-python-6013b0470y-july-2023/page-07.png", + "/Users/juliuseikmans/Desktop/Studies/2025-2026/intro to python/python-exam-cheat-sheet-generator/tmp/exam_coverage_audit/pages/resit-exam-guidelines-for-intro-to-python-6013b0470y-july-2023/page-08.png", + "/Users/juliuseikmans/Desktop/Studies/2025-2026/intro to python/python-exam-cheat-sheet-generator/tmp/exam_coverage_audit/pages/resit-exam-guidelines-for-intro-to-python-6013b0470y-july-2023/page-09.png", + "/Users/juliuseikmans/Desktop/Studies/2025-2026/intro to python/python-exam-cheat-sheet-generator/tmp/exam_coverage_audit/pages/resit-exam-guidelines-for-intro-to-python-6013b0470y-july-2023/page-10.png", + "/Users/juliuseikmans/Desktop/Studies/2025-2026/intro to python/python-exam-cheat-sheet-generator/tmp/exam_coverage_audit/pages/resit-exam-guidelines-for-intro-to-python-6013b0470y-july-2023/page-11.png", + "/Users/juliuseikmans/Desktop/Studies/2025-2026/intro to python/python-exam-cheat-sheet-generator/tmp/exam_coverage_audit/pages/resit-exam-guidelines-for-intro-to-python-6013b0470y-july-2023/page-12.png", + "/Users/juliuseikmans/Desktop/Studies/2025-2026/intro to python/python-exam-cheat-sheet-generator/tmp/exam_coverage_audit/pages/resit-exam-guidelines-for-intro-to-python-6013b0470y-july-2023/page-13.png", + "/Users/juliuseikmans/Desktop/Studies/2025-2026/intro to python/python-exam-cheat-sheet-generator/tmp/exam_coverage_audit/pages/resit-exam-guidelines-for-intro-to-python-6013b0470y-july-2023/page-14.png", + "/Users/juliuseikmans/Desktop/Studies/2025-2026/intro to python/python-exam-cheat-sheet-generator/tmp/exam_coverage_audit/pages/resit-exam-guidelines-for-intro-to-python-6013b0470y-july-2023/page-15.png", + "/Users/juliuseikmans/Desktop/Studies/2025-2026/intro to python/python-exam-cheat-sheet-generator/tmp/exam_coverage_audit/pages/resit-exam-guidelines-for-intro-to-python-6013b0470y-july-2023/page-16.png", + "/Users/juliuseikmans/Desktop/Studies/2025-2026/intro to python/python-exam-cheat-sheet-generator/tmp/exam_coverage_audit/pages/resit-exam-guidelines-for-intro-to-python-6013b0470y-july-2023/page-17.png" + ] + }, + { + "exam_id": "resit-solutions-for-introduction-to-python-35761538", + "title": "2023 Resit Solutions", + "pdf_path": "/Users/juliuseikmans/Desktop/Studies/2025-2026/intro to python/course_files_after_midterm/practice_exams_previous_years/resit-solutions-for-introduction-to-python-35761538.pdf", + "expected_questions": 24, + "page_count": 17, + "page_image_paths": [ + "/Users/juliuseikmans/Desktop/Studies/2025-2026/intro to python/python-exam-cheat-sheet-generator/tmp/exam_coverage_audit/pages/resit-solutions-for-introduction-to-python-35761538/page-01.png", + "/Users/juliuseikmans/Desktop/Studies/2025-2026/intro to python/python-exam-cheat-sheet-generator/tmp/exam_coverage_audit/pages/resit-solutions-for-introduction-to-python-35761538/page-02.png", + "/Users/juliuseikmans/Desktop/Studies/2025-2026/intro to python/python-exam-cheat-sheet-generator/tmp/exam_coverage_audit/pages/resit-solutions-for-introduction-to-python-35761538/page-03.png", + "/Users/juliuseikmans/Desktop/Studies/2025-2026/intro to python/python-exam-cheat-sheet-generator/tmp/exam_coverage_audit/pages/resit-solutions-for-introduction-to-python-35761538/page-04.png", + "/Users/juliuseikmans/Desktop/Studies/2025-2026/intro to python/python-exam-cheat-sheet-generator/tmp/exam_coverage_audit/pages/resit-solutions-for-introduction-to-python-35761538/page-05.png", + "/Users/juliuseikmans/Desktop/Studies/2025-2026/intro to python/python-exam-cheat-sheet-generator/tmp/exam_coverage_audit/pages/resit-solutions-for-introduction-to-python-35761538/page-06.png", + "/Users/juliuseikmans/Desktop/Studies/2025-2026/intro to python/python-exam-cheat-sheet-generator/tmp/exam_coverage_audit/pages/resit-solutions-for-introduction-to-python-35761538/page-07.png", + "/Users/juliuseikmans/Desktop/Studies/2025-2026/intro to python/python-exam-cheat-sheet-generator/tmp/exam_coverage_audit/pages/resit-solutions-for-introduction-to-python-35761538/page-08.png", + "/Users/juliuseikmans/Desktop/Studies/2025-2026/intro to python/python-exam-cheat-sheet-generator/tmp/exam_coverage_audit/pages/resit-solutions-for-introduction-to-python-35761538/page-09.png", + "/Users/juliuseikmans/Desktop/Studies/2025-2026/intro to python/python-exam-cheat-sheet-generator/tmp/exam_coverage_audit/pages/resit-solutions-for-introduction-to-python-35761538/page-10.png", + "/Users/juliuseikmans/Desktop/Studies/2025-2026/intro to python/python-exam-cheat-sheet-generator/tmp/exam_coverage_audit/pages/resit-solutions-for-introduction-to-python-35761538/page-11.png", + "/Users/juliuseikmans/Desktop/Studies/2025-2026/intro to python/python-exam-cheat-sheet-generator/tmp/exam_coverage_audit/pages/resit-solutions-for-introduction-to-python-35761538/page-12.png", + "/Users/juliuseikmans/Desktop/Studies/2025-2026/intro to python/python-exam-cheat-sheet-generator/tmp/exam_coverage_audit/pages/resit-solutions-for-introduction-to-python-35761538/page-13.png", + "/Users/juliuseikmans/Desktop/Studies/2025-2026/intro to python/python-exam-cheat-sheet-generator/tmp/exam_coverage_audit/pages/resit-solutions-for-introduction-to-python-35761538/page-14.png", + "/Users/juliuseikmans/Desktop/Studies/2025-2026/intro to python/python-exam-cheat-sheet-generator/tmp/exam_coverage_audit/pages/resit-solutions-for-introduction-to-python-35761538/page-15.png", + "/Users/juliuseikmans/Desktop/Studies/2025-2026/intro to python/python-exam-cheat-sheet-generator/tmp/exam_coverage_audit/pages/resit-solutions-for-introduction-to-python-35761538/page-16.png", + "/Users/juliuseikmans/Desktop/Studies/2025-2026/intro to python/python-exam-cheat-sheet-generator/tmp/exam_coverage_audit/pages/resit-solutions-for-introduction-to-python-35761538/page-17.png" + ] + }, + { + "exam_id": "trial-final-exam-solutions-introduction-to-python-3077951", + "title": "Trial Final Later-Course Focus", + "pdf_path": "/Users/juliuseikmans/Desktop/Studies/2025-2026/intro to python/course_files_after_midterm/practice_exams_previous_years/trial-final-exam-solutions-introduction-to-python-3077951.pdf", + "expected_questions": 24, + "page_count": 13, + "page_image_paths": [ + "/Users/juliuseikmans/Desktop/Studies/2025-2026/intro to python/python-exam-cheat-sheet-generator/tmp/exam_coverage_audit/pages/trial-final-exam-solutions-introduction-to-python-3077951/page-01.png", + "/Users/juliuseikmans/Desktop/Studies/2025-2026/intro to python/python-exam-cheat-sheet-generator/tmp/exam_coverage_audit/pages/trial-final-exam-solutions-introduction-to-python-3077951/page-02.png", + "/Users/juliuseikmans/Desktop/Studies/2025-2026/intro to python/python-exam-cheat-sheet-generator/tmp/exam_coverage_audit/pages/trial-final-exam-solutions-introduction-to-python-3077951/page-03.png", + "/Users/juliuseikmans/Desktop/Studies/2025-2026/intro to python/python-exam-cheat-sheet-generator/tmp/exam_coverage_audit/pages/trial-final-exam-solutions-introduction-to-python-3077951/page-04.png", + "/Users/juliuseikmans/Desktop/Studies/2025-2026/intro to python/python-exam-cheat-sheet-generator/tmp/exam_coverage_audit/pages/trial-final-exam-solutions-introduction-to-python-3077951/page-05.png", + "/Users/juliuseikmans/Desktop/Studies/2025-2026/intro to python/python-exam-cheat-sheet-generator/tmp/exam_coverage_audit/pages/trial-final-exam-solutions-introduction-to-python-3077951/page-06.png", + "/Users/juliuseikmans/Desktop/Studies/2025-2026/intro to python/python-exam-cheat-sheet-generator/tmp/exam_coverage_audit/pages/trial-final-exam-solutions-introduction-to-python-3077951/page-07.png", + "/Users/juliuseikmans/Desktop/Studies/2025-2026/intro to python/python-exam-cheat-sheet-generator/tmp/exam_coverage_audit/pages/trial-final-exam-solutions-introduction-to-python-3077951/page-08.png", + "/Users/juliuseikmans/Desktop/Studies/2025-2026/intro to python/python-exam-cheat-sheet-generator/tmp/exam_coverage_audit/pages/trial-final-exam-solutions-introduction-to-python-3077951/page-09.png", + "/Users/juliuseikmans/Desktop/Studies/2025-2026/intro to python/python-exam-cheat-sheet-generator/tmp/exam_coverage_audit/pages/trial-final-exam-solutions-introduction-to-python-3077951/page-10.png", + "/Users/juliuseikmans/Desktop/Studies/2025-2026/intro to python/python-exam-cheat-sheet-generator/tmp/exam_coverage_audit/pages/trial-final-exam-solutions-introduction-to-python-3077951/page-11.png", + "/Users/juliuseikmans/Desktop/Studies/2025-2026/intro to python/python-exam-cheat-sheet-generator/tmp/exam_coverage_audit/pages/trial-final-exam-solutions-introduction-to-python-3077951/page-12.png", + "/Users/juliuseikmans/Desktop/Studies/2025-2026/intro to python/python-exam-cheat-sheet-generator/tmp/exam_coverage_audit/pages/trial-final-exam-solutions-introduction-to-python-3077951/page-13.png" + ] + } + ] +} \ No newline at end of file diff --git a/tmp/exam_coverage_audit/pages/final-exam-solutions-for-python-programming-62oop21/page-01.png b/tmp/exam_coverage_audit/pages/final-exam-solutions-for-python-programming-62oop21/page-01.png new file mode 100644 index 0000000..4014165 Binary files /dev/null and b/tmp/exam_coverage_audit/pages/final-exam-solutions-for-python-programming-62oop21/page-01.png differ diff --git a/tmp/exam_coverage_audit/pages/final-exam-solutions-for-python-programming-62oop21/page-02.png b/tmp/exam_coverage_audit/pages/final-exam-solutions-for-python-programming-62oop21/page-02.png new file mode 100644 index 0000000..6c5c001 Binary files /dev/null and b/tmp/exam_coverage_audit/pages/final-exam-solutions-for-python-programming-62oop21/page-02.png differ diff --git a/tmp/exam_coverage_audit/pages/final-exam-solutions-for-python-programming-62oop21/page-03.png b/tmp/exam_coverage_audit/pages/final-exam-solutions-for-python-programming-62oop21/page-03.png new file mode 100644 index 0000000..2ee742d Binary files /dev/null and b/tmp/exam_coverage_audit/pages/final-exam-solutions-for-python-programming-62oop21/page-03.png differ diff --git a/tmp/exam_coverage_audit/pages/final-exam-solutions-for-python-programming-62oop21/page-04.png b/tmp/exam_coverage_audit/pages/final-exam-solutions-for-python-programming-62oop21/page-04.png new file mode 100644 index 0000000..e5e9118 Binary files /dev/null and b/tmp/exam_coverage_audit/pages/final-exam-solutions-for-python-programming-62oop21/page-04.png differ diff --git a/tmp/exam_coverage_audit/pages/final-exam-solutions-for-python-programming-62oop21/page-05.png b/tmp/exam_coverage_audit/pages/final-exam-solutions-for-python-programming-62oop21/page-05.png new file mode 100644 index 0000000..d0b3755 Binary files /dev/null and b/tmp/exam_coverage_audit/pages/final-exam-solutions-for-python-programming-62oop21/page-05.png differ diff --git a/tmp/exam_coverage_audit/pages/final-exam-solutions-for-python-programming-62oop21/page-06.png b/tmp/exam_coverage_audit/pages/final-exam-solutions-for-python-programming-62oop21/page-06.png new file mode 100644 index 0000000..1f75a07 Binary files /dev/null and b/tmp/exam_coverage_audit/pages/final-exam-solutions-for-python-programming-62oop21/page-06.png differ diff --git a/tmp/exam_coverage_audit/pages/final-exam-solutions-for-python-programming-62oop21/page-07.png b/tmp/exam_coverage_audit/pages/final-exam-solutions-for-python-programming-62oop21/page-07.png new file mode 100644 index 0000000..f1bf9c4 Binary files /dev/null and b/tmp/exam_coverage_audit/pages/final-exam-solutions-for-python-programming-62oop21/page-07.png differ diff --git a/tmp/exam_coverage_audit/pages/final-exam-solutions-for-python-programming-62oop21/page-08.png b/tmp/exam_coverage_audit/pages/final-exam-solutions-for-python-programming-62oop21/page-08.png new file mode 100644 index 0000000..518c176 Binary files /dev/null and b/tmp/exam_coverage_audit/pages/final-exam-solutions-for-python-programming-62oop21/page-08.png differ diff --git a/tmp/exam_coverage_audit/pages/final-exam-solutions-for-python-programming-62oop21/page-09.png b/tmp/exam_coverage_audit/pages/final-exam-solutions-for-python-programming-62oop21/page-09.png new file mode 100644 index 0000000..4041a76 Binary files /dev/null and b/tmp/exam_coverage_audit/pages/final-exam-solutions-for-python-programming-62oop21/page-09.png differ diff --git a/tmp/exam_coverage_audit/pages/final-exam-solutions-for-python-programming-62oop21/page-10.png b/tmp/exam_coverage_audit/pages/final-exam-solutions-for-python-programming-62oop21/page-10.png new file mode 100644 index 0000000..e5d1404 Binary files /dev/null and b/tmp/exam_coverage_audit/pages/final-exam-solutions-for-python-programming-62oop21/page-10.png differ diff --git a/tmp/exam_coverage_audit/pages/final-exam-solutions-for-python-programming-62oop21/page-11.png b/tmp/exam_coverage_audit/pages/final-exam-solutions-for-python-programming-62oop21/page-11.png new file mode 100644 index 0000000..ea6489a Binary files /dev/null and b/tmp/exam_coverage_audit/pages/final-exam-solutions-for-python-programming-62oop21/page-11.png differ diff --git a/tmp/exam_coverage_audit/pages/final-exam-solutions-for-python-programming-62oop21/page-12.png b/tmp/exam_coverage_audit/pages/final-exam-solutions-for-python-programming-62oop21/page-12.png new file mode 100644 index 0000000..25af874 Binary files /dev/null and b/tmp/exam_coverage_audit/pages/final-exam-solutions-for-python-programming-62oop21/page-12.png differ diff --git a/tmp/exam_coverage_audit/pages/final-exam-solutions-for-python-programming-62oop21/page-13.png b/tmp/exam_coverage_audit/pages/final-exam-solutions-for-python-programming-62oop21/page-13.png new file mode 100644 index 0000000..605ca57 Binary files /dev/null and b/tmp/exam_coverage_audit/pages/final-exam-solutions-for-python-programming-62oop21/page-13.png differ diff --git a/tmp/exam_coverage_audit/pages/final-exam-solutions-for-python-programming-62oop21/page-14.png b/tmp/exam_coverage_audit/pages/final-exam-solutions-for-python-programming-62oop21/page-14.png new file mode 100644 index 0000000..4b20fd8 Binary files /dev/null and b/tmp/exam_coverage_audit/pages/final-exam-solutions-for-python-programming-62oop21/page-14.png differ diff --git a/tmp/exam_coverage_audit/pages/final-exam-solutions-for-python-programming-62oop21/page-15.png b/tmp/exam_coverage_audit/pages/final-exam-solutions-for-python-programming-62oop21/page-15.png new file mode 100644 index 0000000..8932c13 Binary files /dev/null and b/tmp/exam_coverage_audit/pages/final-exam-solutions-for-python-programming-62oop21/page-15.png differ diff --git a/tmp/exam_coverage_audit/pages/final-exam-study-guide-trial-python-basics-2023-contacts/contact-01.png b/tmp/exam_coverage_audit/pages/final-exam-study-guide-trial-python-basics-2023-contacts/contact-01.png new file mode 100644 index 0000000..ffde170 Binary files /dev/null and b/tmp/exam_coverage_audit/pages/final-exam-study-guide-trial-python-basics-2023-contacts/contact-01.png differ diff --git a/tmp/exam_coverage_audit/pages/final-exam-study-guide-trial-python-basics-2023-contacts/contact-02.png b/tmp/exam_coverage_audit/pages/final-exam-study-guide-trial-python-basics-2023-contacts/contact-02.png new file mode 100644 index 0000000..703ca76 Binary files /dev/null and b/tmp/exam_coverage_audit/pages/final-exam-study-guide-trial-python-basics-2023-contacts/contact-02.png differ diff --git a/tmp/exam_coverage_audit/pages/final-exam-study-guide-trial-python-basics-2023-contacts/contact-03.png b/tmp/exam_coverage_audit/pages/final-exam-study-guide-trial-python-basics-2023-contacts/contact-03.png new file mode 100644 index 0000000..a910f84 Binary files /dev/null and b/tmp/exam_coverage_audit/pages/final-exam-study-guide-trial-python-basics-2023-contacts/contact-03.png differ diff --git a/tmp/exam_coverage_audit/pages/final-exam-study-guide-trial-python-basics-2023-contacts/contact-04.png b/tmp/exam_coverage_audit/pages/final-exam-study-guide-trial-python-basics-2023-contacts/contact-04.png new file mode 100644 index 0000000..fba07c0 Binary files /dev/null and b/tmp/exam_coverage_audit/pages/final-exam-study-guide-trial-python-basics-2023-contacts/contact-04.png differ diff --git a/tmp/exam_coverage_audit/pages/final-exam-study-guide-trial-python-basics-2023-contacts/contact-05.png b/tmp/exam_coverage_audit/pages/final-exam-study-guide-trial-python-basics-2023-contacts/contact-05.png new file mode 100644 index 0000000..1225d46 Binary files /dev/null and b/tmp/exam_coverage_audit/pages/final-exam-study-guide-trial-python-basics-2023-contacts/contact-05.png differ diff --git a/tmp/exam_coverage_audit/pages/final-exam-study-guide-trial-python-basics-2023/page-01.png b/tmp/exam_coverage_audit/pages/final-exam-study-guide-trial-python-basics-2023/page-01.png new file mode 100644 index 0000000..ca9687f Binary files /dev/null and b/tmp/exam_coverage_audit/pages/final-exam-study-guide-trial-python-basics-2023/page-01.png differ diff --git a/tmp/exam_coverage_audit/pages/final-exam-study-guide-trial-python-basics-2023/page-02.png b/tmp/exam_coverage_audit/pages/final-exam-study-guide-trial-python-basics-2023/page-02.png new file mode 100644 index 0000000..ce819a3 Binary files /dev/null and b/tmp/exam_coverage_audit/pages/final-exam-study-guide-trial-python-basics-2023/page-02.png differ diff --git a/tmp/exam_coverage_audit/pages/final-exam-study-guide-trial-python-basics-2023/page-03.png b/tmp/exam_coverage_audit/pages/final-exam-study-guide-trial-python-basics-2023/page-03.png new file mode 100644 index 0000000..0727eff Binary files /dev/null and b/tmp/exam_coverage_audit/pages/final-exam-study-guide-trial-python-basics-2023/page-03.png differ diff --git a/tmp/exam_coverage_audit/pages/final-exam-study-guide-trial-python-basics-2023/page-04.png b/tmp/exam_coverage_audit/pages/final-exam-study-guide-trial-python-basics-2023/page-04.png new file mode 100644 index 0000000..5117d3b Binary files /dev/null and b/tmp/exam_coverage_audit/pages/final-exam-study-guide-trial-python-basics-2023/page-04.png differ diff --git a/tmp/exam_coverage_audit/pages/final-exam-study-guide-trial-python-basics-2023/page-05.png b/tmp/exam_coverage_audit/pages/final-exam-study-guide-trial-python-basics-2023/page-05.png new file mode 100644 index 0000000..3029849 Binary files /dev/null and b/tmp/exam_coverage_audit/pages/final-exam-study-guide-trial-python-basics-2023/page-05.png differ diff --git a/tmp/exam_coverage_audit/pages/final-exam-study-guide-trial-python-basics-2023/page-06.png b/tmp/exam_coverage_audit/pages/final-exam-study-guide-trial-python-basics-2023/page-06.png new file mode 100644 index 0000000..24bcbb8 Binary files /dev/null and b/tmp/exam_coverage_audit/pages/final-exam-study-guide-trial-python-basics-2023/page-06.png differ diff --git a/tmp/exam_coverage_audit/pages/final-exam-study-guide-trial-python-basics-2023/page-07.png b/tmp/exam_coverage_audit/pages/final-exam-study-guide-trial-python-basics-2023/page-07.png new file mode 100644 index 0000000..84200dc Binary files /dev/null and b/tmp/exam_coverage_audit/pages/final-exam-study-guide-trial-python-basics-2023/page-07.png differ diff --git a/tmp/exam_coverage_audit/pages/final-exam-study-guide-trial-python-basics-2023/page-08.png b/tmp/exam_coverage_audit/pages/final-exam-study-guide-trial-python-basics-2023/page-08.png new file mode 100644 index 0000000..3db549d Binary files /dev/null and b/tmp/exam_coverage_audit/pages/final-exam-study-guide-trial-python-basics-2023/page-08.png differ diff --git a/tmp/exam_coverage_audit/pages/final-exam-study-guide-trial-python-basics-2023/page-09.png b/tmp/exam_coverage_audit/pages/final-exam-study-guide-trial-python-basics-2023/page-09.png new file mode 100644 index 0000000..14a7692 Binary files /dev/null and b/tmp/exam_coverage_audit/pages/final-exam-study-guide-trial-python-basics-2023/page-09.png differ diff --git a/tmp/exam_coverage_audit/pages/final-exam-study-guide-trial-python-basics-2023/page-10.png b/tmp/exam_coverage_audit/pages/final-exam-study-guide-trial-python-basics-2023/page-10.png new file mode 100644 index 0000000..3fbbcf4 Binary files /dev/null and b/tmp/exam_coverage_audit/pages/final-exam-study-guide-trial-python-basics-2023/page-10.png differ diff --git a/tmp/exam_coverage_audit/pages/final-exam-study-guide-trial-python-basics-2023/page-11.png b/tmp/exam_coverage_audit/pages/final-exam-study-guide-trial-python-basics-2023/page-11.png new file mode 100644 index 0000000..9742800 Binary files /dev/null and b/tmp/exam_coverage_audit/pages/final-exam-study-guide-trial-python-basics-2023/page-11.png differ diff --git a/tmp/exam_coverage_audit/pages/final-exam-study-guide-trial-python-basics-2023/page-12.png b/tmp/exam_coverage_audit/pages/final-exam-study-guide-trial-python-basics-2023/page-12.png new file mode 100644 index 0000000..0e7b912 Binary files /dev/null and b/tmp/exam_coverage_audit/pages/final-exam-study-guide-trial-python-basics-2023/page-12.png differ diff --git a/tmp/exam_coverage_audit/pages/final-exam-study-guide-trial-python-basics-2023/page-13.png b/tmp/exam_coverage_audit/pages/final-exam-study-guide-trial-python-basics-2023/page-13.png new file mode 100644 index 0000000..7584c84 Binary files /dev/null and b/tmp/exam_coverage_audit/pages/final-exam-study-guide-trial-python-basics-2023/page-13.png differ diff --git a/tmp/exam_coverage_audit/pages/final-exam-study-guide-trial-python-basics-2023/page-14.png b/tmp/exam_coverage_audit/pages/final-exam-study-guide-trial-python-basics-2023/page-14.png new file mode 100644 index 0000000..f5f7a5d Binary files /dev/null and b/tmp/exam_coverage_audit/pages/final-exam-study-guide-trial-python-basics-2023/page-14.png differ diff --git a/tmp/exam_coverage_audit/pages/final-exam-study-guide-trial-python-basics-2023/page-15.png b/tmp/exam_coverage_audit/pages/final-exam-study-guide-trial-python-basics-2023/page-15.png new file mode 100644 index 0000000..3c32dc6 Binary files /dev/null and b/tmp/exam_coverage_audit/pages/final-exam-study-guide-trial-python-basics-2023/page-15.png differ diff --git a/tmp/exam_coverage_audit/pages/final-exam-study-guide-trial-python-basics-2023/page-16.png b/tmp/exam_coverage_audit/pages/final-exam-study-guide-trial-python-basics-2023/page-16.png new file mode 100644 index 0000000..274978f Binary files /dev/null and b/tmp/exam_coverage_audit/pages/final-exam-study-guide-trial-python-basics-2023/page-16.png differ diff --git a/tmp/exam_coverage_audit/pages/final-exam-study-guide-trial-python-basics-2023/page-17.png b/tmp/exam_coverage_audit/pages/final-exam-study-guide-trial-python-basics-2023/page-17.png new file mode 100644 index 0000000..6f7028f Binary files /dev/null and b/tmp/exam_coverage_audit/pages/final-exam-study-guide-trial-python-basics-2023/page-17.png differ diff --git a/tmp/exam_coverage_audit/pages/introduction-to-python-trial-final-exam-solutions-py22/page-01.png b/tmp/exam_coverage_audit/pages/introduction-to-python-trial-final-exam-solutions-py22/page-01.png new file mode 100644 index 0000000..8bd8a69 Binary files /dev/null and b/tmp/exam_coverage_audit/pages/introduction-to-python-trial-final-exam-solutions-py22/page-01.png differ diff --git a/tmp/exam_coverage_audit/pages/introduction-to-python-trial-final-exam-solutions-py22/page-02.png b/tmp/exam_coverage_audit/pages/introduction-to-python-trial-final-exam-solutions-py22/page-02.png new file mode 100644 index 0000000..7f56edd Binary files /dev/null and b/tmp/exam_coverage_audit/pages/introduction-to-python-trial-final-exam-solutions-py22/page-02.png differ diff --git a/tmp/exam_coverage_audit/pages/introduction-to-python-trial-final-exam-solutions-py22/page-03.png b/tmp/exam_coverage_audit/pages/introduction-to-python-trial-final-exam-solutions-py22/page-03.png new file mode 100644 index 0000000..b68230b Binary files /dev/null and b/tmp/exam_coverage_audit/pages/introduction-to-python-trial-final-exam-solutions-py22/page-03.png differ diff --git a/tmp/exam_coverage_audit/pages/introduction-to-python-trial-final-exam-solutions-py22/page-04.png b/tmp/exam_coverage_audit/pages/introduction-to-python-trial-final-exam-solutions-py22/page-04.png new file mode 100644 index 0000000..a884893 Binary files /dev/null and b/tmp/exam_coverage_audit/pages/introduction-to-python-trial-final-exam-solutions-py22/page-04.png differ diff --git a/tmp/exam_coverage_audit/pages/introduction-to-python-trial-final-exam-solutions-py22/page-05.png b/tmp/exam_coverage_audit/pages/introduction-to-python-trial-final-exam-solutions-py22/page-05.png new file mode 100644 index 0000000..ae1167e Binary files /dev/null and b/tmp/exam_coverage_audit/pages/introduction-to-python-trial-final-exam-solutions-py22/page-05.png differ diff --git a/tmp/exam_coverage_audit/pages/introduction-to-python-trial-final-exam-solutions-py22/page-06.png b/tmp/exam_coverage_audit/pages/introduction-to-python-trial-final-exam-solutions-py22/page-06.png new file mode 100644 index 0000000..5b019fd Binary files /dev/null and b/tmp/exam_coverage_audit/pages/introduction-to-python-trial-final-exam-solutions-py22/page-06.png differ diff --git a/tmp/exam_coverage_audit/pages/introduction-to-python-trial-final-exam-solutions-py22/page-07.png b/tmp/exam_coverage_audit/pages/introduction-to-python-trial-final-exam-solutions-py22/page-07.png new file mode 100644 index 0000000..c1dfe89 Binary files /dev/null and b/tmp/exam_coverage_audit/pages/introduction-to-python-trial-final-exam-solutions-py22/page-07.png differ diff --git a/tmp/exam_coverage_audit/pages/introduction-to-python-trial-final-exam-solutions-py22/page-08.png b/tmp/exam_coverage_audit/pages/introduction-to-python-trial-final-exam-solutions-py22/page-08.png new file mode 100644 index 0000000..dd006ba Binary files /dev/null and b/tmp/exam_coverage_audit/pages/introduction-to-python-trial-final-exam-solutions-py22/page-08.png differ diff --git a/tmp/exam_coverage_audit/pages/introduction-to-python-trial-final-exam-solutions-py22/page-09.png b/tmp/exam_coverage_audit/pages/introduction-to-python-trial-final-exam-solutions-py22/page-09.png new file mode 100644 index 0000000..3916a79 Binary files /dev/null and b/tmp/exam_coverage_audit/pages/introduction-to-python-trial-final-exam-solutions-py22/page-09.png differ diff --git a/tmp/exam_coverage_audit/pages/introduction-to-python-trial-final-exam-solutions-py22/page-10.png b/tmp/exam_coverage_audit/pages/introduction-to-python-trial-final-exam-solutions-py22/page-10.png new file mode 100644 index 0000000..e653825 Binary files /dev/null and b/tmp/exam_coverage_audit/pages/introduction-to-python-trial-final-exam-solutions-py22/page-10.png differ diff --git a/tmp/exam_coverage_audit/pages/introduction-to-python-trial-final-exam-solutions-py22/page-11.png b/tmp/exam_coverage_audit/pages/introduction-to-python-trial-final-exam-solutions-py22/page-11.png new file mode 100644 index 0000000..dda99e5 Binary files /dev/null and b/tmp/exam_coverage_audit/pages/introduction-to-python-trial-final-exam-solutions-py22/page-11.png differ diff --git a/tmp/exam_coverage_audit/pages/introduction-to-python-trial-final-exam-solutions-py22/page-12.png b/tmp/exam_coverage_audit/pages/introduction-to-python-trial-final-exam-solutions-py22/page-12.png new file mode 100644 index 0000000..c5dd9ce Binary files /dev/null and b/tmp/exam_coverage_audit/pages/introduction-to-python-trial-final-exam-solutions-py22/page-12.png differ diff --git a/tmp/exam_coverage_audit/pages/introduction-to-python-trial-final-exam-solutions-py22/page-13.png b/tmp/exam_coverage_audit/pages/introduction-to-python-trial-final-exam-solutions-py22/page-13.png new file mode 100644 index 0000000..63b4a98 Binary files /dev/null and b/tmp/exam_coverage_audit/pages/introduction-to-python-trial-final-exam-solutions-py22/page-13.png differ diff --git a/tmp/exam_coverage_audit/pages/introduction-to-python-trial-final-exam-solutions-py22/page-14.png b/tmp/exam_coverage_audit/pages/introduction-to-python-trial-final-exam-solutions-py22/page-14.png new file mode 100644 index 0000000..067fd21 Binary files /dev/null and b/tmp/exam_coverage_audit/pages/introduction-to-python-trial-final-exam-solutions-py22/page-14.png differ diff --git a/tmp/exam_coverage_audit/pages/introduction-to-python-trial-final-exam-solutions-py22/page-15.png b/tmp/exam_coverage_audit/pages/introduction-to-python-trial-final-exam-solutions-py22/page-15.png new file mode 100644 index 0000000..f47dcfb Binary files /dev/null and b/tmp/exam_coverage_audit/pages/introduction-to-python-trial-final-exam-solutions-py22/page-15.png differ diff --git a/tmp/exam_coverage_audit/pages/introduction-to-python-trial-final-exam-solutions-py22/page-16.png b/tmp/exam_coverage_audit/pages/introduction-to-python-trial-final-exam-solutions-py22/page-16.png new file mode 100644 index 0000000..3e83cd9 Binary files /dev/null and b/tmp/exam_coverage_audit/pages/introduction-to-python-trial-final-exam-solutions-py22/page-16.png differ diff --git a/tmp/exam_coverage_audit/pages/introduction-to-python-trial-final-exam-solutions-py22/page-17.png b/tmp/exam_coverage_audit/pages/introduction-to-python-trial-final-exam-solutions-py22/page-17.png new file mode 100644 index 0000000..c5bca0c Binary files /dev/null and b/tmp/exam_coverage_audit/pages/introduction-to-python-trial-final-exam-solutions-py22/page-17.png differ diff --git a/tmp/exam_coverage_audit/pages/resit-exam-guidelines-for-intro-to-python-6013b0470y-july-2023/page-01.png b/tmp/exam_coverage_audit/pages/resit-exam-guidelines-for-intro-to-python-6013b0470y-july-2023/page-01.png new file mode 100644 index 0000000..1be0b61 Binary files /dev/null and b/tmp/exam_coverage_audit/pages/resit-exam-guidelines-for-intro-to-python-6013b0470y-july-2023/page-01.png differ diff --git a/tmp/exam_coverage_audit/pages/resit-exam-guidelines-for-intro-to-python-6013b0470y-july-2023/page-02.png b/tmp/exam_coverage_audit/pages/resit-exam-guidelines-for-intro-to-python-6013b0470y-july-2023/page-02.png new file mode 100644 index 0000000..97e5a9c Binary files /dev/null and b/tmp/exam_coverage_audit/pages/resit-exam-guidelines-for-intro-to-python-6013b0470y-july-2023/page-02.png differ diff --git a/tmp/exam_coverage_audit/pages/resit-exam-guidelines-for-intro-to-python-6013b0470y-july-2023/page-03.png b/tmp/exam_coverage_audit/pages/resit-exam-guidelines-for-intro-to-python-6013b0470y-july-2023/page-03.png new file mode 100644 index 0000000..21f26e4 Binary files /dev/null and b/tmp/exam_coverage_audit/pages/resit-exam-guidelines-for-intro-to-python-6013b0470y-july-2023/page-03.png differ diff --git a/tmp/exam_coverage_audit/pages/resit-exam-guidelines-for-intro-to-python-6013b0470y-july-2023/page-04.png b/tmp/exam_coverage_audit/pages/resit-exam-guidelines-for-intro-to-python-6013b0470y-july-2023/page-04.png new file mode 100644 index 0000000..0d506fd Binary files /dev/null and b/tmp/exam_coverage_audit/pages/resit-exam-guidelines-for-intro-to-python-6013b0470y-july-2023/page-04.png differ diff --git a/tmp/exam_coverage_audit/pages/resit-exam-guidelines-for-intro-to-python-6013b0470y-july-2023/page-05.png b/tmp/exam_coverage_audit/pages/resit-exam-guidelines-for-intro-to-python-6013b0470y-july-2023/page-05.png new file mode 100644 index 0000000..a32351b Binary files /dev/null and b/tmp/exam_coverage_audit/pages/resit-exam-guidelines-for-intro-to-python-6013b0470y-july-2023/page-05.png differ diff --git a/tmp/exam_coverage_audit/pages/resit-exam-guidelines-for-intro-to-python-6013b0470y-july-2023/page-06.png b/tmp/exam_coverage_audit/pages/resit-exam-guidelines-for-intro-to-python-6013b0470y-july-2023/page-06.png new file mode 100644 index 0000000..e7117f8 Binary files /dev/null and b/tmp/exam_coverage_audit/pages/resit-exam-guidelines-for-intro-to-python-6013b0470y-july-2023/page-06.png differ diff --git a/tmp/exam_coverage_audit/pages/resit-exam-guidelines-for-intro-to-python-6013b0470y-july-2023/page-07.png b/tmp/exam_coverage_audit/pages/resit-exam-guidelines-for-intro-to-python-6013b0470y-july-2023/page-07.png new file mode 100644 index 0000000..395f93c Binary files /dev/null and b/tmp/exam_coverage_audit/pages/resit-exam-guidelines-for-intro-to-python-6013b0470y-july-2023/page-07.png differ diff --git a/tmp/exam_coverage_audit/pages/resit-exam-guidelines-for-intro-to-python-6013b0470y-july-2023/page-08.png b/tmp/exam_coverage_audit/pages/resit-exam-guidelines-for-intro-to-python-6013b0470y-july-2023/page-08.png new file mode 100644 index 0000000..5e44c71 Binary files /dev/null and b/tmp/exam_coverage_audit/pages/resit-exam-guidelines-for-intro-to-python-6013b0470y-july-2023/page-08.png differ diff --git a/tmp/exam_coverage_audit/pages/resit-exam-guidelines-for-intro-to-python-6013b0470y-july-2023/page-09.png b/tmp/exam_coverage_audit/pages/resit-exam-guidelines-for-intro-to-python-6013b0470y-july-2023/page-09.png new file mode 100644 index 0000000..f9dbd81 Binary files /dev/null and b/tmp/exam_coverage_audit/pages/resit-exam-guidelines-for-intro-to-python-6013b0470y-july-2023/page-09.png differ diff --git a/tmp/exam_coverage_audit/pages/resit-exam-guidelines-for-intro-to-python-6013b0470y-july-2023/page-10.png b/tmp/exam_coverage_audit/pages/resit-exam-guidelines-for-intro-to-python-6013b0470y-july-2023/page-10.png new file mode 100644 index 0000000..85c01ba Binary files /dev/null and b/tmp/exam_coverage_audit/pages/resit-exam-guidelines-for-intro-to-python-6013b0470y-july-2023/page-10.png differ diff --git a/tmp/exam_coverage_audit/pages/resit-exam-guidelines-for-intro-to-python-6013b0470y-july-2023/page-11.png b/tmp/exam_coverage_audit/pages/resit-exam-guidelines-for-intro-to-python-6013b0470y-july-2023/page-11.png new file mode 100644 index 0000000..e4d2b57 Binary files /dev/null and b/tmp/exam_coverage_audit/pages/resit-exam-guidelines-for-intro-to-python-6013b0470y-july-2023/page-11.png differ diff --git a/tmp/exam_coverage_audit/pages/resit-exam-guidelines-for-intro-to-python-6013b0470y-july-2023/page-12.png b/tmp/exam_coverage_audit/pages/resit-exam-guidelines-for-intro-to-python-6013b0470y-july-2023/page-12.png new file mode 100644 index 0000000..71f40ae Binary files /dev/null and b/tmp/exam_coverage_audit/pages/resit-exam-guidelines-for-intro-to-python-6013b0470y-july-2023/page-12.png differ diff --git a/tmp/exam_coverage_audit/pages/resit-exam-guidelines-for-intro-to-python-6013b0470y-july-2023/page-13.png b/tmp/exam_coverage_audit/pages/resit-exam-guidelines-for-intro-to-python-6013b0470y-july-2023/page-13.png new file mode 100644 index 0000000..9e86a33 Binary files /dev/null and b/tmp/exam_coverage_audit/pages/resit-exam-guidelines-for-intro-to-python-6013b0470y-july-2023/page-13.png differ diff --git a/tmp/exam_coverage_audit/pages/resit-exam-guidelines-for-intro-to-python-6013b0470y-july-2023/page-14.png b/tmp/exam_coverage_audit/pages/resit-exam-guidelines-for-intro-to-python-6013b0470y-july-2023/page-14.png new file mode 100644 index 0000000..05bd25f Binary files /dev/null and b/tmp/exam_coverage_audit/pages/resit-exam-guidelines-for-intro-to-python-6013b0470y-july-2023/page-14.png differ diff --git a/tmp/exam_coverage_audit/pages/resit-exam-guidelines-for-intro-to-python-6013b0470y-july-2023/page-15.png b/tmp/exam_coverage_audit/pages/resit-exam-guidelines-for-intro-to-python-6013b0470y-july-2023/page-15.png new file mode 100644 index 0000000..61acf4a Binary files /dev/null and b/tmp/exam_coverage_audit/pages/resit-exam-guidelines-for-intro-to-python-6013b0470y-july-2023/page-15.png differ diff --git a/tmp/exam_coverage_audit/pages/resit-exam-guidelines-for-intro-to-python-6013b0470y-july-2023/page-16.png b/tmp/exam_coverage_audit/pages/resit-exam-guidelines-for-intro-to-python-6013b0470y-july-2023/page-16.png new file mode 100644 index 0000000..2bd811e Binary files /dev/null and b/tmp/exam_coverage_audit/pages/resit-exam-guidelines-for-intro-to-python-6013b0470y-july-2023/page-16.png differ diff --git a/tmp/exam_coverage_audit/pages/resit-exam-guidelines-for-intro-to-python-6013b0470y-july-2023/page-17.png b/tmp/exam_coverage_audit/pages/resit-exam-guidelines-for-intro-to-python-6013b0470y-july-2023/page-17.png new file mode 100644 index 0000000..262f886 Binary files /dev/null and b/tmp/exam_coverage_audit/pages/resit-exam-guidelines-for-intro-to-python-6013b0470y-july-2023/page-17.png differ diff --git a/tmp/exam_coverage_audit/pages/resit-solutions-for-introduction-to-python-35761538/page-01.png b/tmp/exam_coverage_audit/pages/resit-solutions-for-introduction-to-python-35761538/page-01.png new file mode 100644 index 0000000..9be4a55 Binary files /dev/null and b/tmp/exam_coverage_audit/pages/resit-solutions-for-introduction-to-python-35761538/page-01.png differ diff --git a/tmp/exam_coverage_audit/pages/resit-solutions-for-introduction-to-python-35761538/page-02.png b/tmp/exam_coverage_audit/pages/resit-solutions-for-introduction-to-python-35761538/page-02.png new file mode 100644 index 0000000..ac2bde7 Binary files /dev/null and b/tmp/exam_coverage_audit/pages/resit-solutions-for-introduction-to-python-35761538/page-02.png differ diff --git a/tmp/exam_coverage_audit/pages/resit-solutions-for-introduction-to-python-35761538/page-03.png b/tmp/exam_coverage_audit/pages/resit-solutions-for-introduction-to-python-35761538/page-03.png new file mode 100644 index 0000000..4351c25 Binary files /dev/null and b/tmp/exam_coverage_audit/pages/resit-solutions-for-introduction-to-python-35761538/page-03.png differ diff --git a/tmp/exam_coverage_audit/pages/resit-solutions-for-introduction-to-python-35761538/page-04.png b/tmp/exam_coverage_audit/pages/resit-solutions-for-introduction-to-python-35761538/page-04.png new file mode 100644 index 0000000..6e14107 Binary files /dev/null and b/tmp/exam_coverage_audit/pages/resit-solutions-for-introduction-to-python-35761538/page-04.png differ diff --git a/tmp/exam_coverage_audit/pages/resit-solutions-for-introduction-to-python-35761538/page-05.png b/tmp/exam_coverage_audit/pages/resit-solutions-for-introduction-to-python-35761538/page-05.png new file mode 100644 index 0000000..87cf0c0 Binary files /dev/null and b/tmp/exam_coverage_audit/pages/resit-solutions-for-introduction-to-python-35761538/page-05.png differ diff --git a/tmp/exam_coverage_audit/pages/resit-solutions-for-introduction-to-python-35761538/page-06.png b/tmp/exam_coverage_audit/pages/resit-solutions-for-introduction-to-python-35761538/page-06.png new file mode 100644 index 0000000..8e73f3a Binary files /dev/null and b/tmp/exam_coverage_audit/pages/resit-solutions-for-introduction-to-python-35761538/page-06.png differ diff --git a/tmp/exam_coverage_audit/pages/resit-solutions-for-introduction-to-python-35761538/page-07.png b/tmp/exam_coverage_audit/pages/resit-solutions-for-introduction-to-python-35761538/page-07.png new file mode 100644 index 0000000..0bc6d84 Binary files /dev/null and b/tmp/exam_coverage_audit/pages/resit-solutions-for-introduction-to-python-35761538/page-07.png differ diff --git a/tmp/exam_coverage_audit/pages/resit-solutions-for-introduction-to-python-35761538/page-08.png b/tmp/exam_coverage_audit/pages/resit-solutions-for-introduction-to-python-35761538/page-08.png new file mode 100644 index 0000000..a889d1a Binary files /dev/null and b/tmp/exam_coverage_audit/pages/resit-solutions-for-introduction-to-python-35761538/page-08.png differ diff --git a/tmp/exam_coverage_audit/pages/resit-solutions-for-introduction-to-python-35761538/page-09.png b/tmp/exam_coverage_audit/pages/resit-solutions-for-introduction-to-python-35761538/page-09.png new file mode 100644 index 0000000..0fa5e4c Binary files /dev/null and b/tmp/exam_coverage_audit/pages/resit-solutions-for-introduction-to-python-35761538/page-09.png differ diff --git a/tmp/exam_coverage_audit/pages/resit-solutions-for-introduction-to-python-35761538/page-10.png b/tmp/exam_coverage_audit/pages/resit-solutions-for-introduction-to-python-35761538/page-10.png new file mode 100644 index 0000000..5250241 Binary files /dev/null and b/tmp/exam_coverage_audit/pages/resit-solutions-for-introduction-to-python-35761538/page-10.png differ diff --git a/tmp/exam_coverage_audit/pages/resit-solutions-for-introduction-to-python-35761538/page-11.png b/tmp/exam_coverage_audit/pages/resit-solutions-for-introduction-to-python-35761538/page-11.png new file mode 100644 index 0000000..4acfcae Binary files /dev/null and b/tmp/exam_coverage_audit/pages/resit-solutions-for-introduction-to-python-35761538/page-11.png differ diff --git a/tmp/exam_coverage_audit/pages/resit-solutions-for-introduction-to-python-35761538/page-12.png b/tmp/exam_coverage_audit/pages/resit-solutions-for-introduction-to-python-35761538/page-12.png new file mode 100644 index 0000000..e866b26 Binary files /dev/null and b/tmp/exam_coverage_audit/pages/resit-solutions-for-introduction-to-python-35761538/page-12.png differ diff --git a/tmp/exam_coverage_audit/pages/resit-solutions-for-introduction-to-python-35761538/page-13.png b/tmp/exam_coverage_audit/pages/resit-solutions-for-introduction-to-python-35761538/page-13.png new file mode 100644 index 0000000..6ac1ba4 Binary files /dev/null and b/tmp/exam_coverage_audit/pages/resit-solutions-for-introduction-to-python-35761538/page-13.png differ diff --git a/tmp/exam_coverage_audit/pages/resit-solutions-for-introduction-to-python-35761538/page-14.png b/tmp/exam_coverage_audit/pages/resit-solutions-for-introduction-to-python-35761538/page-14.png new file mode 100644 index 0000000..b811f11 Binary files /dev/null and b/tmp/exam_coverage_audit/pages/resit-solutions-for-introduction-to-python-35761538/page-14.png differ diff --git a/tmp/exam_coverage_audit/pages/resit-solutions-for-introduction-to-python-35761538/page-15.png b/tmp/exam_coverage_audit/pages/resit-solutions-for-introduction-to-python-35761538/page-15.png new file mode 100644 index 0000000..790b439 Binary files /dev/null and b/tmp/exam_coverage_audit/pages/resit-solutions-for-introduction-to-python-35761538/page-15.png differ diff --git a/tmp/exam_coverage_audit/pages/resit-solutions-for-introduction-to-python-35761538/page-16.png b/tmp/exam_coverage_audit/pages/resit-solutions-for-introduction-to-python-35761538/page-16.png new file mode 100644 index 0000000..2f3f54b Binary files /dev/null and b/tmp/exam_coverage_audit/pages/resit-solutions-for-introduction-to-python-35761538/page-16.png differ diff --git a/tmp/exam_coverage_audit/pages/resit-solutions-for-introduction-to-python-35761538/page-17.png b/tmp/exam_coverage_audit/pages/resit-solutions-for-introduction-to-python-35761538/page-17.png new file mode 100644 index 0000000..0f19c1c Binary files /dev/null and b/tmp/exam_coverage_audit/pages/resit-solutions-for-introduction-to-python-35761538/page-17.png differ diff --git a/tmp/exam_coverage_audit/pages/sample-final-plus-answers/contact-sheet.png b/tmp/exam_coverage_audit/pages/sample-final-plus-answers/contact-sheet.png new file mode 100644 index 0000000..50dd89d Binary files /dev/null and b/tmp/exam_coverage_audit/pages/sample-final-plus-answers/contact-sheet.png differ diff --git a/tmp/exam_coverage_audit/pages/sample-final-plus-answers/page-01.png b/tmp/exam_coverage_audit/pages/sample-final-plus-answers/page-01.png new file mode 100644 index 0000000..1581c29 Binary files /dev/null and b/tmp/exam_coverage_audit/pages/sample-final-plus-answers/page-01.png differ diff --git a/tmp/exam_coverage_audit/pages/sample-final-plus-answers/page-02.png b/tmp/exam_coverage_audit/pages/sample-final-plus-answers/page-02.png new file mode 100644 index 0000000..98c8a51 Binary files /dev/null and b/tmp/exam_coverage_audit/pages/sample-final-plus-answers/page-02.png differ diff --git a/tmp/exam_coverage_audit/pages/sample-final-plus-answers/page-03.png b/tmp/exam_coverage_audit/pages/sample-final-plus-answers/page-03.png new file mode 100644 index 0000000..ae4080b Binary files /dev/null and b/tmp/exam_coverage_audit/pages/sample-final-plus-answers/page-03.png differ diff --git a/tmp/exam_coverage_audit/pages/sample-final-plus-answers/page-04.png b/tmp/exam_coverage_audit/pages/sample-final-plus-answers/page-04.png new file mode 100644 index 0000000..5093f4e Binary files /dev/null and b/tmp/exam_coverage_audit/pages/sample-final-plus-answers/page-04.png differ diff --git a/tmp/exam_coverage_audit/pages/sample-final-plus-answers/page-05.png b/tmp/exam_coverage_audit/pages/sample-final-plus-answers/page-05.png new file mode 100644 index 0000000..db6ffda Binary files /dev/null and b/tmp/exam_coverage_audit/pages/sample-final-plus-answers/page-05.png differ diff --git a/tmp/exam_coverage_audit/pages/sample-final-plus-answers/page-06.png b/tmp/exam_coverage_audit/pages/sample-final-plus-answers/page-06.png new file mode 100644 index 0000000..41f6b5c Binary files /dev/null and b/tmp/exam_coverage_audit/pages/sample-final-plus-answers/page-06.png differ diff --git a/tmp/exam_coverage_audit/pages/sample-final-plus-answers/page-07.png b/tmp/exam_coverage_audit/pages/sample-final-plus-answers/page-07.png new file mode 100644 index 0000000..f1d0506 Binary files /dev/null and b/tmp/exam_coverage_audit/pages/sample-final-plus-answers/page-07.png differ diff --git a/tmp/exam_coverage_audit/pages/sample-final-plus-answers/page-08.png b/tmp/exam_coverage_audit/pages/sample-final-plus-answers/page-08.png new file mode 100644 index 0000000..717e898 Binary files /dev/null and b/tmp/exam_coverage_audit/pages/sample-final-plus-answers/page-08.png differ diff --git a/tmp/exam_coverage_audit/pages/sample-final-plus-answers/page-09.png b/tmp/exam_coverage_audit/pages/sample-final-plus-answers/page-09.png new file mode 100644 index 0000000..2a43546 Binary files /dev/null and b/tmp/exam_coverage_audit/pages/sample-final-plus-answers/page-09.png differ diff --git a/tmp/exam_coverage_audit/pages/sample-final-plus-answers/page-10.png b/tmp/exam_coverage_audit/pages/sample-final-plus-answers/page-10.png new file mode 100644 index 0000000..e879322 Binary files /dev/null and b/tmp/exam_coverage_audit/pages/sample-final-plus-answers/page-10.png differ diff --git a/tmp/exam_coverage_audit/pages/sample-final-plus-answers/page-11.png b/tmp/exam_coverage_audit/pages/sample-final-plus-answers/page-11.png new file mode 100644 index 0000000..dc59f7f Binary files /dev/null and b/tmp/exam_coverage_audit/pages/sample-final-plus-answers/page-11.png differ diff --git a/tmp/exam_coverage_audit/pages/sample-final-plus-answers/page-12.png b/tmp/exam_coverage_audit/pages/sample-final-plus-answers/page-12.png new file mode 100644 index 0000000..ebe6331 Binary files /dev/null and b/tmp/exam_coverage_audit/pages/sample-final-plus-answers/page-12.png differ diff --git a/tmp/exam_coverage_audit/pages/sample-final-plus-answers/page-13.png b/tmp/exam_coverage_audit/pages/sample-final-plus-answers/page-13.png new file mode 100644 index 0000000..6c450b8 Binary files /dev/null and b/tmp/exam_coverage_audit/pages/sample-final-plus-answers/page-13.png differ diff --git a/tmp/exam_coverage_audit/pages/sample-final-plus-answers/page-14.png b/tmp/exam_coverage_audit/pages/sample-final-plus-answers/page-14.png new file mode 100644 index 0000000..82bae06 Binary files /dev/null and b/tmp/exam_coverage_audit/pages/sample-final-plus-answers/page-14.png differ diff --git a/tmp/exam_coverage_audit/pages/sample-final-plus-answers/page-15.png b/tmp/exam_coverage_audit/pages/sample-final-plus-answers/page-15.png new file mode 100644 index 0000000..9d580b3 Binary files /dev/null and b/tmp/exam_coverage_audit/pages/sample-final-plus-answers/page-15.png differ diff --git a/tmp/exam_coverage_audit/pages/sample-final-plus-answers/page-16.png b/tmp/exam_coverage_audit/pages/sample-final-plus-answers/page-16.png new file mode 100644 index 0000000..d15f647 Binary files /dev/null and b/tmp/exam_coverage_audit/pages/sample-final-plus-answers/page-16.png differ diff --git a/tmp/exam_coverage_audit/pages/sample-final-plus-answers/page-17.png b/tmp/exam_coverage_audit/pages/sample-final-plus-answers/page-17.png new file mode 100644 index 0000000..ff171c0 Binary files /dev/null and b/tmp/exam_coverage_audit/pages/sample-final-plus-answers/page-17.png differ diff --git a/tmp/exam_coverage_audit/pages/sample-final-plus-answers/page-18.png b/tmp/exam_coverage_audit/pages/sample-final-plus-answers/page-18.png new file mode 100644 index 0000000..bbb15cc Binary files /dev/null and b/tmp/exam_coverage_audit/pages/sample-final-plus-answers/page-18.png differ diff --git a/tmp/exam_coverage_audit/pages/sample-final-plus-answers/page-19.png b/tmp/exam_coverage_audit/pages/sample-final-plus-answers/page-19.png new file mode 100644 index 0000000..ed90bd6 Binary files /dev/null and b/tmp/exam_coverage_audit/pages/sample-final-plus-answers/page-19.png differ diff --git a/tmp/exam_coverage_audit/pages/sample-final-plus-answers/page-20.png b/tmp/exam_coverage_audit/pages/sample-final-plus-answers/page-20.png new file mode 100644 index 0000000..b72a39d Binary files /dev/null and b/tmp/exam_coverage_audit/pages/sample-final-plus-answers/page-20.png differ diff --git a/tmp/exam_coverage_audit/pages/sample-final-plus-answers/page-21.png b/tmp/exam_coverage_audit/pages/sample-final-plus-answers/page-21.png new file mode 100644 index 0000000..02ac2ab Binary files /dev/null and b/tmp/exam_coverage_audit/pages/sample-final-plus-answers/page-21.png differ diff --git a/tmp/exam_coverage_audit/pages/sample-final-plus-answers/page-22.png b/tmp/exam_coverage_audit/pages/sample-final-plus-answers/page-22.png new file mode 100644 index 0000000..9d02d95 Binary files /dev/null and b/tmp/exam_coverage_audit/pages/sample-final-plus-answers/page-22.png differ diff --git a/tmp/exam_coverage_audit/pages/sample-final-plus-answers/page-23.png b/tmp/exam_coverage_audit/pages/sample-final-plus-answers/page-23.png new file mode 100644 index 0000000..39d37e5 Binary files /dev/null and b/tmp/exam_coverage_audit/pages/sample-final-plus-answers/page-23.png differ diff --git a/tmp/exam_coverage_audit/pages/sample-final-plus-answers/page-24.png b/tmp/exam_coverage_audit/pages/sample-final-plus-answers/page-24.png new file mode 100644 index 0000000..c0bd355 Binary files /dev/null and b/tmp/exam_coverage_audit/pages/sample-final-plus-answers/page-24.png differ diff --git a/tmp/exam_coverage_audit/pages/sample-final-plus-answers/page-25.png b/tmp/exam_coverage_audit/pages/sample-final-plus-answers/page-25.png new file mode 100644 index 0000000..ce471c4 Binary files /dev/null and b/tmp/exam_coverage_audit/pages/sample-final-plus-answers/page-25.png differ diff --git a/tmp/exam_coverage_audit/pages/sample-final-plus-answers/page-26.png b/tmp/exam_coverage_audit/pages/sample-final-plus-answers/page-26.png new file mode 100644 index 0000000..5093f4e Binary files /dev/null and b/tmp/exam_coverage_audit/pages/sample-final-plus-answers/page-26.png differ diff --git a/tmp/exam_coverage_audit/pages/sample-final-plus-answers/page-27.png b/tmp/exam_coverage_audit/pages/sample-final-plus-answers/page-27.png new file mode 100644 index 0000000..2d7873b Binary files /dev/null and b/tmp/exam_coverage_audit/pages/sample-final-plus-answers/page-27.png differ diff --git a/tmp/exam_coverage_audit/pages/sample-final-plus-answers/page-28.png b/tmp/exam_coverage_audit/pages/sample-final-plus-answers/page-28.png new file mode 100644 index 0000000..baf1d0c Binary files /dev/null and b/tmp/exam_coverage_audit/pages/sample-final-plus-answers/page-28.png differ diff --git a/tmp/exam_coverage_audit/pages/sample-final-plus-answers/page-29.png b/tmp/exam_coverage_audit/pages/sample-final-plus-answers/page-29.png new file mode 100644 index 0000000..4e9aa3f Binary files /dev/null and b/tmp/exam_coverage_audit/pages/sample-final-plus-answers/page-29.png differ diff --git a/tmp/exam_coverage_audit/pages/sample-final-plus-answers/page-30.png b/tmp/exam_coverage_audit/pages/sample-final-plus-answers/page-30.png new file mode 100644 index 0000000..1fdd093 Binary files /dev/null and b/tmp/exam_coverage_audit/pages/sample-final-plus-answers/page-30.png differ diff --git a/tmp/exam_coverage_audit/pages/sample-final-plus-answers/page-31.png b/tmp/exam_coverage_audit/pages/sample-final-plus-answers/page-31.png new file mode 100644 index 0000000..eba598b Binary files /dev/null and b/tmp/exam_coverage_audit/pages/sample-final-plus-answers/page-31.png differ diff --git a/tmp/exam_coverage_audit/pages/sample-final-plus-answers/rotated-cw/page-01.png b/tmp/exam_coverage_audit/pages/sample-final-plus-answers/rotated-cw/page-01.png new file mode 100644 index 0000000..14cf2e4 Binary files /dev/null and b/tmp/exam_coverage_audit/pages/sample-final-plus-answers/rotated-cw/page-01.png differ diff --git a/tmp/exam_coverage_audit/pages/sample-final-plus-answers/rotated-cw/page-02.png b/tmp/exam_coverage_audit/pages/sample-final-plus-answers/rotated-cw/page-02.png new file mode 100644 index 0000000..32be963 Binary files /dev/null and b/tmp/exam_coverage_audit/pages/sample-final-plus-answers/rotated-cw/page-02.png differ diff --git a/tmp/exam_coverage_audit/pages/sample-final-plus-answers/rotated-cw/page-03.png b/tmp/exam_coverage_audit/pages/sample-final-plus-answers/rotated-cw/page-03.png new file mode 100644 index 0000000..f11a6af Binary files /dev/null and b/tmp/exam_coverage_audit/pages/sample-final-plus-answers/rotated-cw/page-03.png differ diff --git a/tmp/exam_coverage_audit/pages/sample-final-plus-answers/rotated-cw/page-04.png b/tmp/exam_coverage_audit/pages/sample-final-plus-answers/rotated-cw/page-04.png new file mode 100644 index 0000000..0602fe8 Binary files /dev/null and b/tmp/exam_coverage_audit/pages/sample-final-plus-answers/rotated-cw/page-04.png differ diff --git a/tmp/exam_coverage_audit/pages/sample-final-plus-answers/rotated-cw/page-05.png b/tmp/exam_coverage_audit/pages/sample-final-plus-answers/rotated-cw/page-05.png new file mode 100644 index 0000000..abafd61 Binary files /dev/null and b/tmp/exam_coverage_audit/pages/sample-final-plus-answers/rotated-cw/page-05.png differ diff --git a/tmp/exam_coverage_audit/pages/sample-final-plus-answers/rotated-cw/page-06.png b/tmp/exam_coverage_audit/pages/sample-final-plus-answers/rotated-cw/page-06.png new file mode 100644 index 0000000..0680cff Binary files /dev/null and b/tmp/exam_coverage_audit/pages/sample-final-plus-answers/rotated-cw/page-06.png differ diff --git a/tmp/exam_coverage_audit/pages/sample-final-plus-answers/rotated-cw/page-07.png b/tmp/exam_coverage_audit/pages/sample-final-plus-answers/rotated-cw/page-07.png new file mode 100644 index 0000000..99a7624 Binary files /dev/null and b/tmp/exam_coverage_audit/pages/sample-final-plus-answers/rotated-cw/page-07.png differ diff --git a/tmp/exam_coverage_audit/pages/sample-final-plus-answers/rotated-cw/page-08.png b/tmp/exam_coverage_audit/pages/sample-final-plus-answers/rotated-cw/page-08.png new file mode 100644 index 0000000..898d2f2 Binary files /dev/null and b/tmp/exam_coverage_audit/pages/sample-final-plus-answers/rotated-cw/page-08.png differ diff --git a/tmp/exam_coverage_audit/pages/sample-final-plus-answers/rotated-cw/page-09.png b/tmp/exam_coverage_audit/pages/sample-final-plus-answers/rotated-cw/page-09.png new file mode 100644 index 0000000..bc9d2cf Binary files /dev/null and b/tmp/exam_coverage_audit/pages/sample-final-plus-answers/rotated-cw/page-09.png differ diff --git a/tmp/exam_coverage_audit/pages/sample-final-plus-answers/rotated-cw/page-10.png b/tmp/exam_coverage_audit/pages/sample-final-plus-answers/rotated-cw/page-10.png new file mode 100644 index 0000000..7c22d4a Binary files /dev/null and b/tmp/exam_coverage_audit/pages/sample-final-plus-answers/rotated-cw/page-10.png differ diff --git a/tmp/exam_coverage_audit/pages/sample-final-plus-answers/rotated-cw/page-11.png b/tmp/exam_coverage_audit/pages/sample-final-plus-answers/rotated-cw/page-11.png new file mode 100644 index 0000000..092ebef Binary files /dev/null and b/tmp/exam_coverage_audit/pages/sample-final-plus-answers/rotated-cw/page-11.png differ diff --git a/tmp/exam_coverage_audit/pages/sample-final-plus-answers/rotated-cw/page-12.png b/tmp/exam_coverage_audit/pages/sample-final-plus-answers/rotated-cw/page-12.png new file mode 100644 index 0000000..5304d4e Binary files /dev/null and b/tmp/exam_coverage_audit/pages/sample-final-plus-answers/rotated-cw/page-12.png differ diff --git a/tmp/exam_coverage_audit/pages/sample-final-plus-answers/rotated-cw/page-13.png b/tmp/exam_coverage_audit/pages/sample-final-plus-answers/rotated-cw/page-13.png new file mode 100644 index 0000000..f64312a Binary files /dev/null and b/tmp/exam_coverage_audit/pages/sample-final-plus-answers/rotated-cw/page-13.png differ diff --git a/tmp/exam_coverage_audit/pages/sample-final-plus-answers/rotated-cw/page-14.png b/tmp/exam_coverage_audit/pages/sample-final-plus-answers/rotated-cw/page-14.png new file mode 100644 index 0000000..274c798 Binary files /dev/null and b/tmp/exam_coverage_audit/pages/sample-final-plus-answers/rotated-cw/page-14.png differ diff --git a/tmp/exam_coverage_audit/pages/sample-final-plus-answers/rotated-cw/page-15.png b/tmp/exam_coverage_audit/pages/sample-final-plus-answers/rotated-cw/page-15.png new file mode 100644 index 0000000..ed3a174 Binary files /dev/null and b/tmp/exam_coverage_audit/pages/sample-final-plus-answers/rotated-cw/page-15.png differ diff --git a/tmp/exam_coverage_audit/pages/sample-final-plus-answers/rotated-cw/page-16.png b/tmp/exam_coverage_audit/pages/sample-final-plus-answers/rotated-cw/page-16.png new file mode 100644 index 0000000..38616ef Binary files /dev/null and b/tmp/exam_coverage_audit/pages/sample-final-plus-answers/rotated-cw/page-16.png differ diff --git a/tmp/exam_coverage_audit/pages/sample-final-plus-answers/rotated-cw/page-17.png b/tmp/exam_coverage_audit/pages/sample-final-plus-answers/rotated-cw/page-17.png new file mode 100644 index 0000000..4df60fd Binary files /dev/null and b/tmp/exam_coverage_audit/pages/sample-final-plus-answers/rotated-cw/page-17.png differ diff --git a/tmp/exam_coverage_audit/pages/sample-final-plus-answers/rotated-cw/page-18.png b/tmp/exam_coverage_audit/pages/sample-final-plus-answers/rotated-cw/page-18.png new file mode 100644 index 0000000..ca4e01d Binary files /dev/null and b/tmp/exam_coverage_audit/pages/sample-final-plus-answers/rotated-cw/page-18.png differ diff --git a/tmp/exam_coverage_audit/pages/sample-final-plus-answers/rotated-cw/page-19.png b/tmp/exam_coverage_audit/pages/sample-final-plus-answers/rotated-cw/page-19.png new file mode 100644 index 0000000..757bad7 Binary files /dev/null and b/tmp/exam_coverage_audit/pages/sample-final-plus-answers/rotated-cw/page-19.png differ diff --git a/tmp/exam_coverage_audit/pages/sample-final-plus-answers/rotated-cw/page-20.png b/tmp/exam_coverage_audit/pages/sample-final-plus-answers/rotated-cw/page-20.png new file mode 100644 index 0000000..9c96072 Binary files /dev/null and b/tmp/exam_coverage_audit/pages/sample-final-plus-answers/rotated-cw/page-20.png differ diff --git a/tmp/exam_coverage_audit/pages/sample-final-plus-answers/rotated-cw/page-21.png b/tmp/exam_coverage_audit/pages/sample-final-plus-answers/rotated-cw/page-21.png new file mode 100644 index 0000000..88817c1 Binary files /dev/null and b/tmp/exam_coverage_audit/pages/sample-final-plus-answers/rotated-cw/page-21.png differ diff --git a/tmp/exam_coverage_audit/pages/sample-final-plus-answers/rotated-cw/page-22.png b/tmp/exam_coverage_audit/pages/sample-final-plus-answers/rotated-cw/page-22.png new file mode 100644 index 0000000..fceba51 Binary files /dev/null and b/tmp/exam_coverage_audit/pages/sample-final-plus-answers/rotated-cw/page-22.png differ diff --git a/tmp/exam_coverage_audit/pages/sample-final-plus-answers/rotated-cw/page-23.png b/tmp/exam_coverage_audit/pages/sample-final-plus-answers/rotated-cw/page-23.png new file mode 100644 index 0000000..df7d0a2 Binary files /dev/null and b/tmp/exam_coverage_audit/pages/sample-final-plus-answers/rotated-cw/page-23.png differ diff --git a/tmp/exam_coverage_audit/pages/sample-final-plus-answers/rotated-cw/page-24.png b/tmp/exam_coverage_audit/pages/sample-final-plus-answers/rotated-cw/page-24.png new file mode 100644 index 0000000..5733bd2 Binary files /dev/null and b/tmp/exam_coverage_audit/pages/sample-final-plus-answers/rotated-cw/page-24.png differ diff --git a/tmp/exam_coverage_audit/pages/sample-final-plus-answers/rotated-cw/page-25.png b/tmp/exam_coverage_audit/pages/sample-final-plus-answers/rotated-cw/page-25.png new file mode 100644 index 0000000..6edc1c5 Binary files /dev/null and b/tmp/exam_coverage_audit/pages/sample-final-plus-answers/rotated-cw/page-25.png differ diff --git a/tmp/exam_coverage_audit/pages/sample-final-plus-answers/rotated-cw/page-26.png b/tmp/exam_coverage_audit/pages/sample-final-plus-answers/rotated-cw/page-26.png new file mode 100644 index 0000000..0602fe8 Binary files /dev/null and b/tmp/exam_coverage_audit/pages/sample-final-plus-answers/rotated-cw/page-26.png differ diff --git a/tmp/exam_coverage_audit/pages/sample-final-plus-answers/rotated-cw/page-27.png b/tmp/exam_coverage_audit/pages/sample-final-plus-answers/rotated-cw/page-27.png new file mode 100644 index 0000000..a015b7f Binary files /dev/null and b/tmp/exam_coverage_audit/pages/sample-final-plus-answers/rotated-cw/page-27.png differ diff --git a/tmp/exam_coverage_audit/pages/sample-final-plus-answers/rotated-cw/page-28.png b/tmp/exam_coverage_audit/pages/sample-final-plus-answers/rotated-cw/page-28.png new file mode 100644 index 0000000..fd5feb6 Binary files /dev/null and b/tmp/exam_coverage_audit/pages/sample-final-plus-answers/rotated-cw/page-28.png differ diff --git a/tmp/exam_coverage_audit/pages/sample-final-plus-answers/rotated-cw/page-29.png b/tmp/exam_coverage_audit/pages/sample-final-plus-answers/rotated-cw/page-29.png new file mode 100644 index 0000000..9b3ed36 Binary files /dev/null and b/tmp/exam_coverage_audit/pages/sample-final-plus-answers/rotated-cw/page-29.png differ diff --git a/tmp/exam_coverage_audit/pages/sample-final-plus-answers/rotated-cw/page-30.png b/tmp/exam_coverage_audit/pages/sample-final-plus-answers/rotated-cw/page-30.png new file mode 100644 index 0000000..4bfe394 Binary files /dev/null and b/tmp/exam_coverage_audit/pages/sample-final-plus-answers/rotated-cw/page-30.png differ diff --git a/tmp/exam_coverage_audit/pages/sample-final-plus-answers/rotated-cw/page-31.png b/tmp/exam_coverage_audit/pages/sample-final-plus-answers/rotated-cw/page-31.png new file mode 100644 index 0000000..bdece66 Binary files /dev/null and b/tmp/exam_coverage_audit/pages/sample-final-plus-answers/rotated-cw/page-31.png differ diff --git a/tmp/exam_coverage_audit/pages/sample-final-plus-answers/rotated/page-01.png b/tmp/exam_coverage_audit/pages/sample-final-plus-answers/rotated/page-01.png new file mode 100644 index 0000000..9d49aa6 Binary files /dev/null and b/tmp/exam_coverage_audit/pages/sample-final-plus-answers/rotated/page-01.png differ diff --git a/tmp/exam_coverage_audit/pages/sample-final-plus-answers/rotated/page-02.png b/tmp/exam_coverage_audit/pages/sample-final-plus-answers/rotated/page-02.png new file mode 100644 index 0000000..d552471 Binary files /dev/null and b/tmp/exam_coverage_audit/pages/sample-final-plus-answers/rotated/page-02.png differ diff --git a/tmp/exam_coverage_audit/pages/sample-final-plus-answers/rotated/page-03.png b/tmp/exam_coverage_audit/pages/sample-final-plus-answers/rotated/page-03.png new file mode 100644 index 0000000..37b9817 Binary files /dev/null and b/tmp/exam_coverage_audit/pages/sample-final-plus-answers/rotated/page-03.png differ diff --git a/tmp/exam_coverage_audit/pages/sample-final-plus-answers/rotated/page-04.png b/tmp/exam_coverage_audit/pages/sample-final-plus-answers/rotated/page-04.png new file mode 100644 index 0000000..c632c29 Binary files /dev/null and b/tmp/exam_coverage_audit/pages/sample-final-plus-answers/rotated/page-04.png differ diff --git a/tmp/exam_coverage_audit/pages/sample-final-plus-answers/rotated/page-05.png b/tmp/exam_coverage_audit/pages/sample-final-plus-answers/rotated/page-05.png new file mode 100644 index 0000000..b62d34b Binary files /dev/null and b/tmp/exam_coverage_audit/pages/sample-final-plus-answers/rotated/page-05.png differ diff --git a/tmp/exam_coverage_audit/pages/sample-final-plus-answers/rotated/page-06.png b/tmp/exam_coverage_audit/pages/sample-final-plus-answers/rotated/page-06.png new file mode 100644 index 0000000..6bd805a Binary files /dev/null and b/tmp/exam_coverage_audit/pages/sample-final-plus-answers/rotated/page-06.png differ diff --git a/tmp/exam_coverage_audit/pages/sample-final-plus-answers/rotated/page-07.png b/tmp/exam_coverage_audit/pages/sample-final-plus-answers/rotated/page-07.png new file mode 100644 index 0000000..f86e76a Binary files /dev/null and b/tmp/exam_coverage_audit/pages/sample-final-plus-answers/rotated/page-07.png differ diff --git a/tmp/exam_coverage_audit/pages/sample-final-plus-answers/rotated/page-08.png b/tmp/exam_coverage_audit/pages/sample-final-plus-answers/rotated/page-08.png new file mode 100644 index 0000000..a52890e Binary files /dev/null and b/tmp/exam_coverage_audit/pages/sample-final-plus-answers/rotated/page-08.png differ diff --git a/tmp/exam_coverage_audit/pages/sample-final-plus-answers/rotated/page-09.png b/tmp/exam_coverage_audit/pages/sample-final-plus-answers/rotated/page-09.png new file mode 100644 index 0000000..afa2142 Binary files /dev/null and b/tmp/exam_coverage_audit/pages/sample-final-plus-answers/rotated/page-09.png differ diff --git a/tmp/exam_coverage_audit/pages/sample-final-plus-answers/rotated/page-10.png b/tmp/exam_coverage_audit/pages/sample-final-plus-answers/rotated/page-10.png new file mode 100644 index 0000000..79d5c95 Binary files /dev/null and b/tmp/exam_coverage_audit/pages/sample-final-plus-answers/rotated/page-10.png differ diff --git a/tmp/exam_coverage_audit/pages/sample-final-plus-answers/rotated/page-11.png b/tmp/exam_coverage_audit/pages/sample-final-plus-answers/rotated/page-11.png new file mode 100644 index 0000000..a8672c2 Binary files /dev/null and b/tmp/exam_coverage_audit/pages/sample-final-plus-answers/rotated/page-11.png differ diff --git a/tmp/exam_coverage_audit/pages/sample-final-plus-answers/rotated/page-12.png b/tmp/exam_coverage_audit/pages/sample-final-plus-answers/rotated/page-12.png new file mode 100644 index 0000000..131881c Binary files /dev/null and b/tmp/exam_coverage_audit/pages/sample-final-plus-answers/rotated/page-12.png differ diff --git a/tmp/exam_coverage_audit/pages/sample-final-plus-answers/rotated/page-13.png b/tmp/exam_coverage_audit/pages/sample-final-plus-answers/rotated/page-13.png new file mode 100644 index 0000000..4653572 Binary files /dev/null and b/tmp/exam_coverage_audit/pages/sample-final-plus-answers/rotated/page-13.png differ diff --git a/tmp/exam_coverage_audit/pages/sample-final-plus-answers/rotated/page-14.png b/tmp/exam_coverage_audit/pages/sample-final-plus-answers/rotated/page-14.png new file mode 100644 index 0000000..d5903a8 Binary files /dev/null and b/tmp/exam_coverage_audit/pages/sample-final-plus-answers/rotated/page-14.png differ diff --git a/tmp/exam_coverage_audit/pages/sample-final-plus-answers/rotated/page-15.png b/tmp/exam_coverage_audit/pages/sample-final-plus-answers/rotated/page-15.png new file mode 100644 index 0000000..0cef8ca Binary files /dev/null and b/tmp/exam_coverage_audit/pages/sample-final-plus-answers/rotated/page-15.png differ diff --git a/tmp/exam_coverage_audit/pages/sample-final-plus-answers/rotated/page-16.png b/tmp/exam_coverage_audit/pages/sample-final-plus-answers/rotated/page-16.png new file mode 100644 index 0000000..6399775 Binary files /dev/null and b/tmp/exam_coverage_audit/pages/sample-final-plus-answers/rotated/page-16.png differ diff --git a/tmp/exam_coverage_audit/pages/sample-final-plus-answers/rotated/page-17.png b/tmp/exam_coverage_audit/pages/sample-final-plus-answers/rotated/page-17.png new file mode 100644 index 0000000..7322ef1 Binary files /dev/null and b/tmp/exam_coverage_audit/pages/sample-final-plus-answers/rotated/page-17.png differ diff --git a/tmp/exam_coverage_audit/pages/sample-final-plus-answers/rotated/page-18.png b/tmp/exam_coverage_audit/pages/sample-final-plus-answers/rotated/page-18.png new file mode 100644 index 0000000..bf01731 Binary files /dev/null and b/tmp/exam_coverage_audit/pages/sample-final-plus-answers/rotated/page-18.png differ diff --git a/tmp/exam_coverage_audit/pages/sample-final-plus-answers/rotated/page-19.png b/tmp/exam_coverage_audit/pages/sample-final-plus-answers/rotated/page-19.png new file mode 100644 index 0000000..062410f Binary files /dev/null and b/tmp/exam_coverage_audit/pages/sample-final-plus-answers/rotated/page-19.png differ diff --git a/tmp/exam_coverage_audit/pages/sample-final-plus-answers/rotated/page-20.png b/tmp/exam_coverage_audit/pages/sample-final-plus-answers/rotated/page-20.png new file mode 100644 index 0000000..bad4a80 Binary files /dev/null and b/tmp/exam_coverage_audit/pages/sample-final-plus-answers/rotated/page-20.png differ diff --git a/tmp/exam_coverage_audit/pages/sample-final-plus-answers/rotated/page-21.png b/tmp/exam_coverage_audit/pages/sample-final-plus-answers/rotated/page-21.png new file mode 100644 index 0000000..5c20b15 Binary files /dev/null and b/tmp/exam_coverage_audit/pages/sample-final-plus-answers/rotated/page-21.png differ diff --git a/tmp/exam_coverage_audit/pages/sample-final-plus-answers/rotated/page-22.png b/tmp/exam_coverage_audit/pages/sample-final-plus-answers/rotated/page-22.png new file mode 100644 index 0000000..0526bf3 Binary files /dev/null and b/tmp/exam_coverage_audit/pages/sample-final-plus-answers/rotated/page-22.png differ diff --git a/tmp/exam_coverage_audit/pages/sample-final-plus-answers/rotated/page-23.png b/tmp/exam_coverage_audit/pages/sample-final-plus-answers/rotated/page-23.png new file mode 100644 index 0000000..b789b6f Binary files /dev/null and b/tmp/exam_coverage_audit/pages/sample-final-plus-answers/rotated/page-23.png differ diff --git a/tmp/exam_coverage_audit/pages/sample-final-plus-answers/rotated/page-24.png b/tmp/exam_coverage_audit/pages/sample-final-plus-answers/rotated/page-24.png new file mode 100644 index 0000000..a9a818f Binary files /dev/null and b/tmp/exam_coverage_audit/pages/sample-final-plus-answers/rotated/page-24.png differ diff --git a/tmp/exam_coverage_audit/pages/sample-final-plus-answers/rotated/page-25.png b/tmp/exam_coverage_audit/pages/sample-final-plus-answers/rotated/page-25.png new file mode 100644 index 0000000..3896876 Binary files /dev/null and b/tmp/exam_coverage_audit/pages/sample-final-plus-answers/rotated/page-25.png differ diff --git a/tmp/exam_coverage_audit/pages/sample-final-plus-answers/rotated/page-26.png b/tmp/exam_coverage_audit/pages/sample-final-plus-answers/rotated/page-26.png new file mode 100644 index 0000000..c632c29 Binary files /dev/null and b/tmp/exam_coverage_audit/pages/sample-final-plus-answers/rotated/page-26.png differ diff --git a/tmp/exam_coverage_audit/pages/sample-final-plus-answers/rotated/page-27.png b/tmp/exam_coverage_audit/pages/sample-final-plus-answers/rotated/page-27.png new file mode 100644 index 0000000..45dafdf Binary files /dev/null and b/tmp/exam_coverage_audit/pages/sample-final-plus-answers/rotated/page-27.png differ diff --git a/tmp/exam_coverage_audit/pages/sample-final-plus-answers/rotated/page-28.png b/tmp/exam_coverage_audit/pages/sample-final-plus-answers/rotated/page-28.png new file mode 100644 index 0000000..abe461c Binary files /dev/null and b/tmp/exam_coverage_audit/pages/sample-final-plus-answers/rotated/page-28.png differ diff --git a/tmp/exam_coverage_audit/pages/sample-final-plus-answers/rotated/page-29.png b/tmp/exam_coverage_audit/pages/sample-final-plus-answers/rotated/page-29.png new file mode 100644 index 0000000..a854294 Binary files /dev/null and b/tmp/exam_coverage_audit/pages/sample-final-plus-answers/rotated/page-29.png differ diff --git a/tmp/exam_coverage_audit/pages/sample-final-plus-answers/rotated/page-30.png b/tmp/exam_coverage_audit/pages/sample-final-plus-answers/rotated/page-30.png new file mode 100644 index 0000000..e41c79d Binary files /dev/null and b/tmp/exam_coverage_audit/pages/sample-final-plus-answers/rotated/page-30.png differ diff --git a/tmp/exam_coverage_audit/pages/sample-final-plus-answers/rotated/page-31.png b/tmp/exam_coverage_audit/pages/sample-final-plus-answers/rotated/page-31.png new file mode 100644 index 0000000..e180fb6 Binary files /dev/null and b/tmp/exam_coverage_audit/pages/sample-final-plus-answers/rotated/page-31.png differ diff --git a/tmp/exam_coverage_audit/pages/trial-final-exam-solutions-introduction-to-python-3077951/contact-sheet.png b/tmp/exam_coverage_audit/pages/trial-final-exam-solutions-introduction-to-python-3077951/contact-sheet.png new file mode 100644 index 0000000..001f085 Binary files /dev/null and b/tmp/exam_coverage_audit/pages/trial-final-exam-solutions-introduction-to-python-3077951/contact-sheet.png differ diff --git a/tmp/exam_coverage_audit/pages/trial-final-exam-solutions-introduction-to-python-3077951/page-01.png b/tmp/exam_coverage_audit/pages/trial-final-exam-solutions-introduction-to-python-3077951/page-01.png new file mode 100644 index 0000000..4c6f457 Binary files /dev/null and b/tmp/exam_coverage_audit/pages/trial-final-exam-solutions-introduction-to-python-3077951/page-01.png differ diff --git a/tmp/exam_coverage_audit/pages/trial-final-exam-solutions-introduction-to-python-3077951/page-02.png b/tmp/exam_coverage_audit/pages/trial-final-exam-solutions-introduction-to-python-3077951/page-02.png new file mode 100644 index 0000000..f455784 Binary files /dev/null and b/tmp/exam_coverage_audit/pages/trial-final-exam-solutions-introduction-to-python-3077951/page-02.png differ diff --git a/tmp/exam_coverage_audit/pages/trial-final-exam-solutions-introduction-to-python-3077951/page-03.png b/tmp/exam_coverage_audit/pages/trial-final-exam-solutions-introduction-to-python-3077951/page-03.png new file mode 100644 index 0000000..0f7352f Binary files /dev/null and b/tmp/exam_coverage_audit/pages/trial-final-exam-solutions-introduction-to-python-3077951/page-03.png differ diff --git a/tmp/exam_coverage_audit/pages/trial-final-exam-solutions-introduction-to-python-3077951/page-04.png b/tmp/exam_coverage_audit/pages/trial-final-exam-solutions-introduction-to-python-3077951/page-04.png new file mode 100644 index 0000000..df6c540 Binary files /dev/null and b/tmp/exam_coverage_audit/pages/trial-final-exam-solutions-introduction-to-python-3077951/page-04.png differ diff --git a/tmp/exam_coverage_audit/pages/trial-final-exam-solutions-introduction-to-python-3077951/page-05.png b/tmp/exam_coverage_audit/pages/trial-final-exam-solutions-introduction-to-python-3077951/page-05.png new file mode 100644 index 0000000..b4109f0 Binary files /dev/null and b/tmp/exam_coverage_audit/pages/trial-final-exam-solutions-introduction-to-python-3077951/page-05.png differ diff --git a/tmp/exam_coverage_audit/pages/trial-final-exam-solutions-introduction-to-python-3077951/page-06.png b/tmp/exam_coverage_audit/pages/trial-final-exam-solutions-introduction-to-python-3077951/page-06.png new file mode 100644 index 0000000..441be9d Binary files /dev/null and b/tmp/exam_coverage_audit/pages/trial-final-exam-solutions-introduction-to-python-3077951/page-06.png differ diff --git a/tmp/exam_coverage_audit/pages/trial-final-exam-solutions-introduction-to-python-3077951/page-07.png b/tmp/exam_coverage_audit/pages/trial-final-exam-solutions-introduction-to-python-3077951/page-07.png new file mode 100644 index 0000000..81fc6b3 Binary files /dev/null and b/tmp/exam_coverage_audit/pages/trial-final-exam-solutions-introduction-to-python-3077951/page-07.png differ diff --git a/tmp/exam_coverage_audit/pages/trial-final-exam-solutions-introduction-to-python-3077951/page-08.png b/tmp/exam_coverage_audit/pages/trial-final-exam-solutions-introduction-to-python-3077951/page-08.png new file mode 100644 index 0000000..b0bc6fb Binary files /dev/null and b/tmp/exam_coverage_audit/pages/trial-final-exam-solutions-introduction-to-python-3077951/page-08.png differ diff --git a/tmp/exam_coverage_audit/pages/trial-final-exam-solutions-introduction-to-python-3077951/page-09.png b/tmp/exam_coverage_audit/pages/trial-final-exam-solutions-introduction-to-python-3077951/page-09.png new file mode 100644 index 0000000..966d253 Binary files /dev/null and b/tmp/exam_coverage_audit/pages/trial-final-exam-solutions-introduction-to-python-3077951/page-09.png differ diff --git a/tmp/exam_coverage_audit/pages/trial-final-exam-solutions-introduction-to-python-3077951/page-10.png b/tmp/exam_coverage_audit/pages/trial-final-exam-solutions-introduction-to-python-3077951/page-10.png new file mode 100644 index 0000000..a5f0a4a Binary files /dev/null and b/tmp/exam_coverage_audit/pages/trial-final-exam-solutions-introduction-to-python-3077951/page-10.png differ diff --git a/tmp/exam_coverage_audit/pages/trial-final-exam-solutions-introduction-to-python-3077951/page-11.png b/tmp/exam_coverage_audit/pages/trial-final-exam-solutions-introduction-to-python-3077951/page-11.png new file mode 100644 index 0000000..6d52727 Binary files /dev/null and b/tmp/exam_coverage_audit/pages/trial-final-exam-solutions-introduction-to-python-3077951/page-11.png differ diff --git a/tmp/exam_coverage_audit/pages/trial-final-exam-solutions-introduction-to-python-3077951/page-12.png b/tmp/exam_coverage_audit/pages/trial-final-exam-solutions-introduction-to-python-3077951/page-12.png new file mode 100644 index 0000000..81d4a12 Binary files /dev/null and b/tmp/exam_coverage_audit/pages/trial-final-exam-solutions-introduction-to-python-3077951/page-12.png differ diff --git a/tmp/exam_coverage_audit/pages/trial-final-exam-solutions-introduction-to-python-3077951/page-13.png b/tmp/exam_coverage_audit/pages/trial-final-exam-solutions-introduction-to-python-3077951/page-13.png new file mode 100644 index 0000000..feb7090 Binary files /dev/null and b/tmp/exam_coverage_audit/pages/trial-final-exam-solutions-introduction-to-python-3077951/page-13.png differ diff --git a/tmp/exam_coverage_audit/sample_final_findings.json b/tmp/exam_coverage_audit/sample_final_findings.json new file mode 100644 index 0000000..cf031b1 --- /dev/null +++ b/tmp/exam_coverage_audit/sample_final_findings.json @@ -0,0 +1,444 @@ +{ + "exams": [ + { + "exam_id": "sample-final-plus-answers", + "question_count_found": 24, + "question_pages_used": [ + 2, + 3, + 4, + 5, + 6, + 7, + 8, + 9, + 10, + 11, + 12, + 13, + 14, + 15, + 16, + 17, + 18, + 19, + 20, + 21, + 22, + 23, + 24, + 25 + ], + "questions": [ + { + "question_number": 1, + "question_summary": "You'd like to define a class called Vehicle. It should have two attributes: name and mode, which you want to be initialized during object creation. The name attribute can be any st", + "score": 3, + "evidence_item_ids": [ + "exam-intro_python_sample_final_24_25-1-w5-pandas-core-structures" + ], + "evidence_topics": [ + "Pandas Core Structures" + ], + "evidence_buckets": [ + "recommended" + ], + "rationale": "Exact selectable source_exam item for this question exists in the current builder corpus.", + "ai_summary_would_help": false, + "ai_summary_note": "" + }, + { + "question_number": 2, + "question_summary": "Suppose that we create a Book object and call its add_review method three times, like this: book_1 = Book(\"The Lightning Thief\", \"Rick Riordan\"), book_1.add_review(5), book_1.add_r", + "score": 3, + "evidence_item_ids": [ + "exam-intro_python_sample_final_24_25-2-w5-pandas-core-structures" + ], + "evidence_topics": [ + "Pandas Core Structures" + ], + "evidence_buckets": [ + "recommended" + ], + "rationale": "Exact selectable source_exam item for this question exists in the current builder corpus.", + "ai_summary_would_help": false, + "ai_summary_note": "" + }, + { + "question_number": 3, + "question_summary": "Imagine that you have a list called students, which is populated by a number of dictionaries. Each dictionary has keys: \"Name\" and \"Grade\". You'd like to print the text: [NAME] has", + "score": 3, + "evidence_item_ids": [ + "exam-intro_python_sample_final_24_25-3-w3-defining-and-calling-functions" + ], + "evidence_topics": [ + "Defining and Calling Functions" + ], + "evidence_buckets": [ + "recommended" + ], + "rationale": "Exact selectable source_exam item for this question exists in the current builder corpus.", + "ai_summary_would_help": false, + "ai_summary_note": "" + }, + { + "question_number": 4, + "question_summary": "Which of the following code segments does NOT achieve the goal of returning a string with 10 digits by removing dashes?", + "score": 3, + "evidence_item_ids": [ + "exam-intro_python_sample_final_24_25-4-w2-conditions" + ], + "evidence_topics": [ + "Conditions" + ], + "evidence_buckets": [ + "additional" + ], + "rationale": "Exact selectable source_exam item for this question exists in the current builder corpus.", + "ai_summary_would_help": false, + "ai_summary_note": "" + }, + { + "question_number": 5, + "question_summary": "You have a pandas DataFrame called df with columns \"A\" and \"B\". You'd like to create a column called \"C\", which contains the sum of the numbers in columns \"A\" and \"B\". Which of the", + "score": 3, + "evidence_item_ids": [ + "exam-intro_python_sample_final_24_25-5-w4-string-fundamentals" + ], + "evidence_topics": [ + "String Fundamentals" + ], + "evidence_buckets": [ + "recommended" + ], + "rationale": "Exact selectable source_exam item for this question exists in the current builder corpus.", + "ai_summary_would_help": false, + "ai_summary_note": "" + }, + { + "question_number": 6, + "question_summary": "Suppose that you'd like to create a new DataFrame that contains only column 'B' for rows with indices 2, 4, and 6. Which of the following code lines will achieve what you want?", + "score": 3, + "evidence_item_ids": [ + "exam-intro_python_sample_final_24_25-6-w4-string-operations-and-methods" + ], + "evidence_topics": [ + "String Operations and Methods" + ], + "evidence_buckets": [ + "recommended" + ], + "rationale": "Exact selectable source_exam item for this question exists in the current builder corpus.", + "ai_summary_would_help": false, + "ai_summary_note": "" + }, + { + "question_number": 7, + "question_summary": "Which of the following code lines could NOT have created df2 from df1?", + "score": 3, + "evidence_item_ids": [ + "exam-intro_python_sample_final_24_25-7-w4-string-fundamentals" + ], + "evidence_topics": [ + "String Fundamentals" + ], + "evidence_buckets": [ + "recommended" + ], + "rationale": "Exact selectable source_exam item for this question exists in the current builder corpus.", + "ai_summary_would_help": false, + "ai_summary_note": "" + }, + { + "question_number": 8, + "question_summary": "You have a Series s with municipality and province names separated by \"; \". You'd like to create a new Series that only contains the municipality names. Which of the following code", + "score": 3, + "evidence_item_ids": [ + "exam-intro_python_sample_final_24_25-8-w4-string-fundamentals" + ], + "evidence_topics": [ + "String Fundamentals" + ], + "evidence_buckets": [ + "recommended" + ], + "rationale": "Exact selectable source_exam item for this question exists in the current builder corpus.", + "ai_summary_would_help": false, + "ai_summary_note": "" + }, + { + "question_number": 9, + "question_summary": "Suppose that you call the function like this: get_months([\"03/02/2013\", \"03.02.2013\", \"03-02-2013\"]). What does the function call return?", + "score": 3, + "evidence_item_ids": [ + "exam-intro_python_sample_final_24_25-9-w6-datetime" + ], + "evidence_topics": [ + "Datetime" + ], + "evidence_buckets": [ + "recommended" + ], + "rationale": "Exact selectable source_exam item for this question exists in the current builder corpus.", + "ai_summary_would_help": false, + "ai_summary_note": "" + }, + { + "question_number": 10, + "question_summary": "Which of the following code segments will return the number of the day (1-366) that a datetime value represents within the year?", + "score": 3, + "evidence_item_ids": [ + "exam-intro_python_sample_final_24_25-10-w6-datetime" + ], + "evidence_topics": [ + "Datetime" + ], + "evidence_buckets": [ + "recommended" + ], + "rationale": "Exact selectable source_exam item for this question exists in the current builder corpus.", + "ai_summary_would_help": false, + "ai_summary_note": "" + }, + { + "question_number": 11, + "question_summary": "Which of the following code lines will create a dictionary, in which the keys are the elements of list_1 and the values are the number of characters in the corresponding key?", + "score": 3, + "evidence_item_ids": [ + "exam-intro_python_sample_final_24_25-11-w3-defining-and-calling-functions" + ], + "evidence_topics": [ + "Defining and Calling Functions" + ], + "evidence_buckets": [ + "recommended" + ], + "rationale": "Exact selectable source_exam item for this question exists in the current builder corpus.", + "ai_summary_would_help": false, + "ai_summary_note": "" + }, + { + "question_number": 12, + "question_summary": "You'd like to turn every upper case letter in a list into lower case and vice versa. Which code line achieves this?", + "score": 3, + "evidence_item_ids": [ + "exam-intro_python_sample_final_24_25-12-w2-conditions" + ], + "evidence_topics": [ + "Conditions" + ], + "evidence_buckets": [ + "additional" + ], + "rationale": "Exact selectable source_exam item for this question exists in the current builder corpus.", + "ai_summary_would_help": false, + "ai_summary_note": "" + }, + { + "question_number": 13, + "question_summary": "What are the outputs of the following lines of code? print(x == y), print(y == z), print(x == z), print(x == y == z)", + "score": 3, + "evidence_item_ids": [ + "exam-intro_python_sample_final_24_25-13-w1-objects-and-names" + ], + "evidence_topics": [ + "Objects and Names" + ], + "evidence_buckets": [ + "additional" + ], + "rationale": "Exact selectable source_exam item for this question exists in the current builder corpus.", + "ai_summary_would_help": false, + "ai_summary_note": "" + }, + { + "question_number": 14, + "question_summary": "Choose the program that iterates over integers from 1 to 10 and prints the sum of the current and previous number (starting with 0 as previous).", + "score": 3, + "evidence_item_ids": [ + "exam-intro_python_sample_final_24_25-14-w2-loops" + ], + "evidence_topics": [ + "Loops" + ], + "evidence_buckets": [ + "additional" + ], + "rationale": "Exact selectable source_exam item for this question exists in the current builder corpus.", + "ai_summary_would_help": false, + "ai_summary_note": "" + }, + { + "question_number": 15, + "question_summary": "Executing the following program will produce an error. Why?", + "score": 3, + "evidence_item_ids": [ + "exam-intro_python_sample_final_24_25-15-w2-conditions" + ], + "evidence_topics": [ + "Conditions" + ], + "evidence_buckets": [ + "additional" + ], + "rationale": "Exact selectable source_exam item for this question exists in the current builder corpus.", + "ai_summary_would_help": false, + "ai_summary_note": "" + }, + { + "question_number": 16, + "question_summary": "What would be printed by the following code snippet: print(list_1[0](1, 2) ** list_1[1](1, 2))", + "score": 3, + "evidence_item_ids": [ + "exam-intro_python_sample_final_24_25-16-w3-higher-order-patterns" + ], + "evidence_topics": [ + "Higher-Order Patterns" + ], + "evidence_buckets": [ + "additional" + ], + "rationale": "Exact selectable source_exam item for this question exists in the current builder corpus.", + "ai_summary_would_help": false, + "ai_summary_note": "" + }, + { + "question_number": 17, + "question_summary": "What will be printed by the function calls in the main function provided?", + "score": 3, + "evidence_item_ids": [ + "exam-intro_python_sample_final_24_25-17-w3-defining-and-calling-functions" + ], + "evidence_topics": [ + "Defining and Calling Functions" + ], + "evidence_buckets": [ + "additional" + ], + "rationale": "Exact selectable source_exam item for this question exists in the current builder corpus.", + "ai_summary_would_help": false, + "ai_summary_note": "" + }, + { + "question_number": 18, + "question_summary": "How do you break a list into a list of lists, where each sublist contains 3 elements?", + "score": 3, + "evidence_item_ids": [ + "exam-intro_python_sample_final_24_25-18-w2-conditions" + ], + "evidence_topics": [ + "Conditions" + ], + "evidence_buckets": [ + "additional" + ], + "rationale": "Exact selectable source_exam item for this question exists in the current builder corpus.", + "ai_summary_would_help": false, + "ai_summary_note": "" + }, + { + "question_number": 19, + "question_summary": "Which of the following programs correctly returns a dictionary where values are sums of input values whose keys are <= the output key?", + "score": 3, + "evidence_item_ids": [ + "exam-intro_python_sample_final_24_25-19-w3-defining-and-calling-functions" + ], + "evidence_topics": [ + "Defining and Calling Functions" + ], + "evidence_buckets": [ + "additional" + ], + "rationale": "Exact selectable source_exam item for this question exists in the current builder corpus.", + "ai_summary_would_help": false, + "ai_summary_note": "" + }, + { + "question_number": 20, + "question_summary": "What is the result of the program comparing d1 (from zip) and d2 (from enumerate)?", + "score": 3, + "evidence_item_ids": [ + "exam-intro_python_sample_final_24_25-20-w3-defining-and-calling-functions" + ], + "evidence_topics": [ + "Defining and Calling Functions" + ], + "evidence_buckets": [ + "additional" + ], + "rationale": "Exact selectable source_exam item for this question exists in the current builder corpus.", + "ai_summary_would_help": false, + "ai_summary_note": "" + }, + { + "question_number": 21, + "question_summary": "The following codes all print the same value, except one. Which one?", + "score": 3, + "evidence_item_ids": [ + "exam-intro_python_sample_final_24_25-21-w3-defining-and-calling-functions" + ], + "evidence_topics": [ + "Defining and Calling Functions" + ], + "evidence_buckets": [ + "additional" + ], + "rationale": "Exact selectable source_exam item for this question exists in the current builder corpus.", + "ai_summary_would_help": false, + "ai_summary_note": "" + }, + { + "question_number": 22, + "question_summary": "Which script, using the count string method, would print the value 1 for x = 'Amsterdam'?", + "score": 3, + "evidence_item_ids": [ + "exam-intro_python_sample_final_24_25-22-w2-conditions" + ], + "evidence_topics": [ + "Conditions" + ], + "evidence_buckets": [ + "additional" + ], + "rationale": "Exact selectable source_exam item for this question exists in the current builder corpus.", + "ai_summary_would_help": false, + "ai_summary_note": "" + }, + { + "question_number": 23, + "question_summary": "Which of the following function calls would return the number 30 as a result?", + "score": 3, + "evidence_item_ids": [ + "exam-intro_python_sample_final_24_25-23-w3-arguments" + ], + "evidence_topics": [ + "Arguments" + ], + "evidence_buckets": [ + "additional" + ], + "rationale": "Exact selectable source_exam item for this question exists in the current builder corpus.", + "ai_summary_would_help": false, + "ai_summary_note": "" + }, + { + "question_number": 24, + "question_summary": "Which script does NOT print the correct answer for the area of a circle?", + "score": 3, + "evidence_item_ids": [ + "exam-intro_python_sample_final_24_25-24-w2-conditions" + ], + "evidence_topics": [ + "Conditions" + ], + "evidence_buckets": [ + "additional" + ], + "rationale": "Exact selectable source_exam item for this question exists in the current builder corpus.", + "ai_summary_would_help": false, + "ai_summary_note": "" + } + ] + } + ] +} \ No newline at end of file diff --git a/tmp/exam_coverage_audit/seed_exact_matches.json b/tmp/exam_coverage_audit/seed_exact_matches.json new file mode 100644 index 0000000..7b0f614 --- /dev/null +++ b/tmp/exam_coverage_audit/seed_exact_matches.json @@ -0,0 +1,1107 @@ +{ + "exams": [ + { + "exam_id": "sample-final-plus-answers", + "question_count_found": 24, + "question_pages_used": [], + "questions": [ + { + "question_number": 1, + "question_summary": "You'd like to define a class called Vehicle. It should have two attributes: name and mode, which you want to be initialized during object creation. The name attribute can be any st", + "score": 3, + "evidence_item_ids": [ + "exam-intro_python_sample_final_24_25-1-w5-pandas-core-structures" + ], + "evidence_topics": [ + "Pandas Core Structures" + ], + "evidence_buckets": [ + "recommended" + ], + "rationale": "This exact practice-exam question is already available as a selectable exam snippet in the builder.", + "ai_summary_would_help": false, + "ai_summary_note": "" + }, + { + "question_number": 2, + "question_summary": "Suppose that we create a Book object and call its add_review method three times, like this: book_1 = Book(\"The Lightning Thief\", \"Rick Riordan\"), book_1.add_review(5), book_1.add_r", + "score": 3, + "evidence_item_ids": [ + "exam-intro_python_sample_final_24_25-2-w5-pandas-core-structures" + ], + "evidence_topics": [ + "Pandas Core Structures" + ], + "evidence_buckets": [ + "recommended" + ], + "rationale": "This exact practice-exam question is already available as a selectable exam snippet in the builder.", + "ai_summary_would_help": false, + "ai_summary_note": "" + }, + { + "question_number": 3, + "question_summary": "Imagine that you have a list called students, which is populated by a number of dictionaries. Each dictionary has keys: \"Name\" and \"Grade\". You'd like to print the text: [NAME] has", + "score": 3, + "evidence_item_ids": [ + "exam-intro_python_sample_final_24_25-3-w3-defining-and-calling-functions" + ], + "evidence_topics": [ + "Defining and Calling Functions" + ], + "evidence_buckets": [ + "recommended" + ], + "rationale": "This exact practice-exam question is already available as a selectable exam snippet in the builder.", + "ai_summary_would_help": false, + "ai_summary_note": "" + }, + { + "question_number": 4, + "question_summary": "Which of the following code segments does NOT achieve the goal of returning a string with 10 digits by removing dashes?", + "score": 3, + "evidence_item_ids": [ + "exam-intro_python_sample_final_24_25-4-w2-conditions" + ], + "evidence_topics": [ + "Conditions" + ], + "evidence_buckets": [ + "additional" + ], + "rationale": "This exact practice-exam question is already available as a selectable exam snippet in the builder.", + "ai_summary_would_help": false, + "ai_summary_note": "" + }, + { + "question_number": 5, + "question_summary": "You have a pandas DataFrame called df with columns \"A\" and \"B\". You'd like to create a column called \"C\", which contains the sum of the numbers in columns \"A\" and \"B\". Which of the", + "score": 3, + "evidence_item_ids": [ + "exam-intro_python_sample_final_24_25-5-w4-string-fundamentals" + ], + "evidence_topics": [ + "String Fundamentals" + ], + "evidence_buckets": [ + "recommended" + ], + "rationale": "This exact practice-exam question is already available as a selectable exam snippet in the builder.", + "ai_summary_would_help": false, + "ai_summary_note": "" + }, + { + "question_number": 6, + "question_summary": "Suppose that you'd like to create a new DataFrame that contains only column 'B' for rows with indices 2, 4, and 6. Which of the following code lines will achieve what you want?", + "score": 3, + "evidence_item_ids": [ + "exam-intro_python_sample_final_24_25-6-w4-string-operations-and-methods" + ], + "evidence_topics": [ + "String Operations and Methods" + ], + "evidence_buckets": [ + "recommended" + ], + "rationale": "This exact practice-exam question is already available as a selectable exam snippet in the builder.", + "ai_summary_would_help": false, + "ai_summary_note": "" + }, + { + "question_number": 7, + "question_summary": "Which of the following code lines could NOT have created df2 from df1?", + "score": 3, + "evidence_item_ids": [ + "exam-intro_python_sample_final_24_25-7-w4-string-fundamentals" + ], + "evidence_topics": [ + "String Fundamentals" + ], + "evidence_buckets": [ + "recommended" + ], + "rationale": "This exact practice-exam question is already available as a selectable exam snippet in the builder.", + "ai_summary_would_help": false, + "ai_summary_note": "" + }, + { + "question_number": 8, + "question_summary": "You have a Series s with municipality and province names separated by \"; \". You'd like to create a new Series that only contains the municipality names. Which of the following code", + "score": 3, + "evidence_item_ids": [ + "exam-intro_python_sample_final_24_25-8-w4-string-fundamentals" + ], + "evidence_topics": [ + "String Fundamentals" + ], + "evidence_buckets": [ + "recommended" + ], + "rationale": "This exact practice-exam question is already available as a selectable exam snippet in the builder.", + "ai_summary_would_help": false, + "ai_summary_note": "" + }, + { + "question_number": 9, + "question_summary": "Suppose that you call the function like this: get_months([\"03/02/2013\", \"03.02.2013\", \"03-02-2013\"]). What does the function call return?", + "score": 3, + "evidence_item_ids": [ + "exam-intro_python_sample_final_24_25-9-w6-datetime" + ], + "evidence_topics": [ + "Datetime" + ], + "evidence_buckets": [ + "recommended" + ], + "rationale": "This exact practice-exam question is already available as a selectable exam snippet in the builder.", + "ai_summary_would_help": false, + "ai_summary_note": "" + }, + { + "question_number": 10, + "question_summary": "Which of the following code segments will return the number of the day (1-366) that a datetime value represents within the year?", + "score": 3, + "evidence_item_ids": [ + "exam-intro_python_sample_final_24_25-10-w6-datetime" + ], + "evidence_topics": [ + "Datetime" + ], + "evidence_buckets": [ + "recommended" + ], + "rationale": "This exact practice-exam question is already available as a selectable exam snippet in the builder.", + "ai_summary_would_help": false, + "ai_summary_note": "" + }, + { + "question_number": 11, + "question_summary": "Which of the following code lines will create a dictionary, in which the keys are the elements of list_1 and the values are the number of characters in the corresponding key?", + "score": 3, + "evidence_item_ids": [ + "exam-intro_python_sample_final_24_25-11-w3-defining-and-calling-functions" + ], + "evidence_topics": [ + "Defining and Calling Functions" + ], + "evidence_buckets": [ + "recommended" + ], + "rationale": "This exact practice-exam question is already available as a selectable exam snippet in the builder.", + "ai_summary_would_help": false, + "ai_summary_note": "" + }, + { + "question_number": 12, + "question_summary": "You'd like to turn every upper case letter in a list into lower case and vice versa. Which code line achieves this?", + "score": 3, + "evidence_item_ids": [ + "exam-intro_python_sample_final_24_25-12-w2-conditions" + ], + "evidence_topics": [ + "Conditions" + ], + "evidence_buckets": [ + "additional" + ], + "rationale": "This exact practice-exam question is already available as a selectable exam snippet in the builder.", + "ai_summary_would_help": false, + "ai_summary_note": "" + }, + { + "question_number": 13, + "question_summary": "What are the outputs of the following lines of code? print(x == y), print(y == z), print(x == z), print(x == y == z)", + "score": 3, + "evidence_item_ids": [ + "exam-intro_python_sample_final_24_25-13-w1-objects-and-names" + ], + "evidence_topics": [ + "Objects and Names" + ], + "evidence_buckets": [ + "additional" + ], + "rationale": "This exact practice-exam question is already available as a selectable exam snippet in the builder.", + "ai_summary_would_help": false, + "ai_summary_note": "" + }, + { + "question_number": 14, + "question_summary": "Choose the program that iterates over integers from 1 to 10 and prints the sum of the current and previous number (starting with 0 as previous).", + "score": 3, + "evidence_item_ids": [ + "exam-intro_python_sample_final_24_25-14-w2-loops" + ], + "evidence_topics": [ + "Loops" + ], + "evidence_buckets": [ + "additional" + ], + "rationale": "This exact practice-exam question is already available as a selectable exam snippet in the builder.", + "ai_summary_would_help": false, + "ai_summary_note": "" + }, + { + "question_number": 15, + "question_summary": "Executing the following program will produce an error. Why?", + "score": 3, + "evidence_item_ids": [ + "exam-intro_python_sample_final_24_25-15-w2-conditions" + ], + "evidence_topics": [ + "Conditions" + ], + "evidence_buckets": [ + "additional" + ], + "rationale": "This exact practice-exam question is already available as a selectable exam snippet in the builder.", + "ai_summary_would_help": false, + "ai_summary_note": "" + }, + { + "question_number": 16, + "question_summary": "What would be printed by the following code snippet: print(list_1[0](1, 2) ** list_1[1](1, 2))", + "score": 3, + "evidence_item_ids": [ + "exam-intro_python_sample_final_24_25-16-w3-higher-order-patterns" + ], + "evidence_topics": [ + "Higher-Order Patterns" + ], + "evidence_buckets": [ + "additional" + ], + "rationale": "This exact practice-exam question is already available as a selectable exam snippet in the builder.", + "ai_summary_would_help": false, + "ai_summary_note": "" + }, + { + "question_number": 17, + "question_summary": "What will be printed by the function calls in the main function provided?", + "score": 3, + "evidence_item_ids": [ + "exam-intro_python_sample_final_24_25-17-w3-defining-and-calling-functions" + ], + "evidence_topics": [ + "Defining and Calling Functions" + ], + "evidence_buckets": [ + "additional" + ], + "rationale": "This exact practice-exam question is already available as a selectable exam snippet in the builder.", + "ai_summary_would_help": false, + "ai_summary_note": "" + }, + { + "question_number": 18, + "question_summary": "How do you break a list into a list of lists, where each sublist contains 3 elements?", + "score": 3, + "evidence_item_ids": [ + "exam-intro_python_sample_final_24_25-18-w2-conditions" + ], + "evidence_topics": [ + "Conditions" + ], + "evidence_buckets": [ + "additional" + ], + "rationale": "This exact practice-exam question is already available as a selectable exam snippet in the builder.", + "ai_summary_would_help": false, + "ai_summary_note": "" + }, + { + "question_number": 19, + "question_summary": "Which of the following programs correctly returns a dictionary where values are sums of input values whose keys are <= the output key?", + "score": 3, + "evidence_item_ids": [ + "exam-intro_python_sample_final_24_25-19-w3-defining-and-calling-functions" + ], + "evidence_topics": [ + "Defining and Calling Functions" + ], + "evidence_buckets": [ + "additional" + ], + "rationale": "This exact practice-exam question is already available as a selectable exam snippet in the builder.", + "ai_summary_would_help": false, + "ai_summary_note": "" + }, + { + "question_number": 20, + "question_summary": "What is the result of the program comparing d1 (from zip) and d2 (from enumerate)?", + "score": 3, + "evidence_item_ids": [ + "exam-intro_python_sample_final_24_25-20-w3-defining-and-calling-functions" + ], + "evidence_topics": [ + "Defining and Calling Functions" + ], + "evidence_buckets": [ + "additional" + ], + "rationale": "This exact practice-exam question is already available as a selectable exam snippet in the builder.", + "ai_summary_would_help": false, + "ai_summary_note": "" + }, + { + "question_number": 21, + "question_summary": "The following codes all print the same value, except one. Which one?", + "score": 3, + "evidence_item_ids": [ + "exam-intro_python_sample_final_24_25-21-w3-defining-and-calling-functions" + ], + "evidence_topics": [ + "Defining and Calling Functions" + ], + "evidence_buckets": [ + "additional" + ], + "rationale": "This exact practice-exam question is already available as a selectable exam snippet in the builder.", + "ai_summary_would_help": false, + "ai_summary_note": "" + }, + { + "question_number": 22, + "question_summary": "Which script, using the count string method, would print the value 1 for x = 'Amsterdam'?", + "score": 3, + "evidence_item_ids": [ + "exam-intro_python_sample_final_24_25-22-w2-conditions" + ], + "evidence_topics": [ + "Conditions" + ], + "evidence_buckets": [ + "additional" + ], + "rationale": "This exact practice-exam question is already available as a selectable exam snippet in the builder.", + "ai_summary_would_help": false, + "ai_summary_note": "" + }, + { + "question_number": 23, + "question_summary": "Which of the following function calls would return the number 30 as a result?", + "score": 3, + "evidence_item_ids": [ + "exam-intro_python_sample_final_24_25-23-w3-arguments" + ], + "evidence_topics": [ + "Arguments" + ], + "evidence_buckets": [ + "additional" + ], + "rationale": "This exact practice-exam question is already available as a selectable exam snippet in the builder.", + "ai_summary_would_help": false, + "ai_summary_note": "" + }, + { + "question_number": 24, + "question_summary": "Which script does NOT print the correct answer for the area of a circle?", + "score": 3, + "evidence_item_ids": [ + "exam-intro_python_sample_final_24_25-24-w2-conditions" + ], + "evidence_topics": [ + "Conditions" + ], + "evidence_buckets": [ + "additional" + ], + "rationale": "This exact practice-exam question is already available as a selectable exam snippet in the builder.", + "ai_summary_would_help": false, + "ai_summary_note": "" + } + ] + }, + { + "exam_id": "final-exam-solutions-for-python-programming-62oop21", + "question_count_found": 6, + "question_pages_used": [], + "questions": [ + { + "question_number": 1, + "question_summary": "Given the class definition above, trying to execute the following two code lines will result in a Python error. my_flight = Flight(\"KLM\", \"Amsterdam\", \"Paris\") # Code line 1 my_fli", + "score": 3, + "evidence_item_ids": [ + "exam-Test Exam 07-06-22-1-w4-oop-fundamentals" + ], + "evidence_topics": [ + "OOP Fundamentals" + ], + "evidence_buckets": [ + "recommended" + ], + "rationale": "This exact practice-exam question is already available as a selectable exam snippet in the builder.", + "ai_summary_would_help": false, + "ai_summary_note": "" + }, + { + "question_number": 2, + "question_summary": "Suppose that you also want to write a method called compare that compares the book to another book and gives a recommendation for which one to read. A book is better than another b", + "score": 3, + "evidence_item_ids": [ + "exam-Test Exam 07-06-22-2-w4-oop-fundamentals" + ], + "evidence_topics": [ + "OOP Fundamentals" + ], + "evidence_buckets": [ + "recommended" + ], + "rationale": "This exact practice-exam question is already available as a selectable exam snippet in the builder.", + "ai_summary_would_help": false, + "ai_summary_note": "" + }, + { + "question_number": 3, + "question_summary": "You would like to write a function called get_tld that extracts the top-level domain from the URL of a website. The function takes the URL as the input string in the following form", + "score": 3, + "evidence_item_ids": [ + "exam-Test Exam 07-06-22-3-w3-defining-and-calling-functions" + ], + "evidence_topics": [ + "Defining and Calling Functions" + ], + "evidence_buckets": [ + "recommended" + ], + "rationale": "This exact practice-exam question is already available as a selectable exam snippet in the builder.", + "ai_summary_would_help": false, + "ai_summary_note": "" + }, + { + "question_number": 4, + "question_summary": "You're trying to write a function called is_anagram, which takes two strings as inputs and checks whether they are anagrams of each other. That is: whether one of them can be writt", + "score": 3, + "evidence_item_ids": [ + "exam-Test Exam 07-06-22-4-w2-conditions" + ], + "evidence_topics": [ + "Conditions" + ], + "evidence_buckets": [ + "additional" + ], + "rationale": "This exact practice-exam question is already available as a selectable exam snippet in the builder.", + "ai_summary_would_help": false, + "ai_summary_note": "" + }, + { + "question_number": 4, + "question_summary": "You're trying to write a function called is_anagram, which takes two strings as inputs and checks whether they are anagrams of each other. That is: whether one of them can be writt", + "score": 3, + "evidence_item_ids": [ + "exam-Test Exam 07-06-22-4-w3-defining-and-calling-functions" + ], + "evidence_topics": [ + "Defining and Calling Functions" + ], + "evidence_buckets": [ + "recommended" + ], + "rationale": "This exact practice-exam question is already available as a selectable exam snippet in the builder.", + "ai_summary_would_help": false, + "ai_summary_note": "" + }, + { + "question_number": 5, + "question_summary": "You have a pandas Series called s, which contains floats. You'd like to create a new Series, in which each element is equal to the square of the difference between the correspondin", + "score": 3, + "evidence_item_ids": [ + "exam-Test Exam 07-06-22-5-w5-pandas-core-structures" + ], + "evidence_topics": [ + "Pandas Core Structures" + ], + "evidence_buckets": [ + "recommended" + ], + "rationale": "This exact practice-exam question is already available as a selectable exam snippet in the builder.", + "ai_summary_would_help": false, + "ai_summary_note": "" + } + ] + }, + { + "exam_id": "final-exam-study-guide-trial-python-basics-2023", + "question_count_found": 6, + "question_pages_used": [], + "questions": [ + { + "question_number": 1, + "question_summary": "Suppose you already have: (i) a list of strings called europe which contain the names of all European countries, and (ii) a string variable called destination. You want to write a ", + "score": 3, + "evidence_item_ids": [ + "exam-Trial final - Introduction to Python - 22/23-1-w1-objects-and-names" + ], + "evidence_topics": [ + "Objects and Names" + ], + "evidence_buckets": [ + "additional" + ], + "rationale": "This exact practice-exam question is already available as a selectable exam snippet in the builder.", + "ai_summary_would_help": false, + "ai_summary_note": "" + }, + { + "question_number": 2, + "question_summary": "Calling the function func_1() will produce an error. Which line of the following code segment produces the error?", + "score": 3, + "evidence_item_ids": [ + "exam-Trial final - Introduction to Python - 22/23-2-w3-scope" + ], + "evidence_topics": [ + "Scope" + ], + "evidence_buckets": [ + "recommended" + ], + "rationale": "This exact practice-exam question is already available as a selectable exam snippet in the builder.", + "ai_summary_would_help": false, + "ai_summary_note": "" + }, + { + "question_number": 3, + "question_summary": "What is the output of the following code segment?", + "score": 3, + "evidence_item_ids": [ + "exam-Trial final - Introduction to Python - 22/23-3-w3-return-behavior" + ], + "evidence_topics": [ + "Return Behavior" + ], + "evidence_buckets": [ + "recommended" + ], + "rationale": "This exact practice-exam question is already available as a selectable exam snippet in the builder.", + "ai_summary_would_help": false, + "ai_summary_note": "" + }, + { + "question_number": 4, + "question_summary": "You have to create a dictionary called vowels_ASCII where the keys are the lowercase vowels (a, e, i, o, u) and the values are their corresponding ASCII values. The ASCII (American", + "score": 3, + "evidence_item_ids": [ + "exam-Trial final - Introduction to Python - 22/23-4-w2-dictionaries-and-mappings" + ], + "evidence_topics": [ + "Dictionaries and Mappings" + ], + "evidence_buckets": [ + "additional" + ], + "rationale": "This exact practice-exam question is already available as a selectable exam snippet in the builder.", + "ai_summary_would_help": false, + "ai_summary_note": "" + }, + { + "question_number": 5, + "question_summary": "Suppose you have three variables called player1_goals, player2_goals, and player3_goals. Each of the variables contains a list of integers that represents the number of goals score", + "score": 3, + "evidence_item_ids": [ + "exam-Trial final - Introduction to Python - 22/23-5-w2-dictionaries-and-mappings" + ], + "evidence_topics": [ + "Dictionaries and Mappings" + ], + "evidence_buckets": [ + "additional" + ], + "rationale": "This exact practice-exam question is already available as a selectable exam snippet in the builder.", + "ai_summary_would_help": false, + "ai_summary_note": "" + }, + { + "question_number": 6, + "question_summary": "You have the following dictionary that represents the monthly sales of a store: monthly_sales = {'January': 1500, 'February': 2200, 'March': 1800, 'April': 2400, 'May': 2000, 'June", + "score": 3, + "evidence_item_ids": [ + "exam-Trial final - Introduction to Python - 22/23-6-w2-dictionaries-and-mappings" + ], + "evidence_topics": [ + "Dictionaries and Mappings" + ], + "evidence_buckets": [ + "additional" + ], + "rationale": "This exact practice-exam question is already available as a selectable exam snippet in the builder.", + "ai_summary_would_help": false, + "ai_summary_note": "" + } + ] + }, + { + "exam_id": "introduction-to-python-trial-final-exam-solutions-py22", + "question_count_found": 7, + "question_pages_used": [], + "questions": [ + { + "question_number": 1, + "question_summary": "Suppose you have a variable called x which contains an integer between 0 and 10 (both are inclusive). Which of the following programs will tell you whether x contains an odd or eve", + "score": 3, + "evidence_item_ids": [ + "exam-trial-final-exam-py22-1-w1-objects-and-names" + ], + "evidence_topics": [ + "Objects and Names" + ], + "evidence_buckets": [ + "additional" + ], + "rationale": "This exact practice-exam question is already available as a selectable exam snippet in the builder.", + "ai_summary_would_help": false, + "ai_summary_note": "" + }, + { + "question_number": 2, + "question_summary": "Take a look at the following code segment. Will executing this code segment produce an error? If yes, then why?", + "score": 3, + "evidence_item_ids": [ + "exam-trial-final-exam-py22-2-w3-scope" + ], + "evidence_topics": [ + "Scope" + ], + "evidence_buckets": [ + "additional" + ], + "rationale": "This exact practice-exam question is already available as a selectable exam snippet in the builder.", + "ai_summary_would_help": false, + "ai_summary_note": "" + }, + { + "question_number": 3, + "question_summary": "What will be returned by the following code segment?", + "score": 3, + "evidence_item_ids": [ + "exam-trial-final-exam-py22-3-w3-return-behavior" + ], + "evidence_topics": [ + "Return Behavior" + ], + "evidence_buckets": [ + "additional" + ], + "rationale": "This exact practice-exam question is already available as a selectable exam snippet in the builder.", + "ai_summary_would_help": false, + "ai_summary_note": "" + }, + { + "question_number": 4, + "question_summary": "You have to create a dictionary called roman_nums where the keys are the integers from 1 to 5 (both are inclusive) and the values are their corresponding Roman numeral symbols. Tha", + "score": 3, + "evidence_item_ids": [ + "exam-trial-final-exam-py22-4-w2-dictionaries-and-mappings" + ], + "evidence_topics": [ + "Dictionaries and Mappings" + ], + "evidence_buckets": [ + "additional" + ], + "rationale": "This exact practice-exam question is already available as a selectable exam snippet in the builder.", + "ai_summary_would_help": false, + "ai_summary_note": "" + }, + { + "question_number": 5, + "question_summary": "You have two lists representing the names and ages of individuals: names = ['Alice', 'Bob', 'Charlie', 'David'] ages = [25, 30, 35, 40] You need to create a dictionary called perso", + "score": 3, + "evidence_item_ids": [ + "exam-trial-final-exam-py22-5-w2-dictionaries-and-mappings" + ], + "evidence_topics": [ + "Dictionaries and Mappings" + ], + "evidence_buckets": [ + "additional" + ], + "rationale": "This exact practice-exam question is already available as a selectable exam snippet in the builder.", + "ai_summary_would_help": false, + "ai_summary_note": "" + }, + { + "question_number": 6, + "question_summary": "You have the following dictionary that represents the performance ratings of employees in a company: employee_ratings = {'John': 8, 'Sarah': 9, 'Michael': 7, 'Emma': 9, 'David': 6}", + "score": 3, + "evidence_item_ids": [ + "exam-trial-final-exam-py22-6-w2-dictionaries-and-mappings" + ], + "evidence_topics": [ + "Dictionaries and Mappings" + ], + "evidence_buckets": [ + "additional" + ], + "rationale": "This exact practice-exam question is already available as a selectable exam snippet in the builder.", + "ai_summary_would_help": false, + "ai_summary_note": "" + }, + { + "question_number": 7, + "question_summary": "What is the output of the following code segment?", + "score": 3, + "evidence_item_ids": [ + "exam-trial-final-exam-py22-7-w2-lists-and-sets" + ], + "evidence_topics": [ + "Lists and Sets" + ], + "evidence_buckets": [ + "additional" + ], + "rationale": "This exact practice-exam question is already available as a selectable exam snippet in the builder.", + "ai_summary_would_help": false, + "ai_summary_note": "" + } + ] + }, + { + "exam_id": "resit-exam-guidelines-for-intro-to-python-6013b0470y-july-2023", + "question_count_found": 6, + "question_pages_used": [], + "questions": [ + { + "question_number": 1, + "question_summary": "Suppose you have a list called x containing tuples, where x = [(1, 2), (3, 4), (5, 6), (7, 8)] Which of the following lines of code will print True?", + "score": 3, + "evidence_item_ids": [ + "exam-Test Resit - Introduction to Python - 22/23-1-w2-lists-and-sets" + ], + "evidence_topics": [ + "Lists and Sets" + ], + "evidence_buckets": [ + "additional" + ], + "rationale": "This exact practice-exam question is already available as a selectable exam snippet in the builder.", + "ai_summary_would_help": false, + "ai_summary_note": "" + }, + { + "question_number": 2, + "question_summary": "Executing the following program will produce an error. Why?", + "score": 3, + "evidence_item_ids": [ + "exam-Test Resit - Introduction to Python - 22/23-2-w3-scope" + ], + "evidence_topics": [ + "Scope" + ], + "evidence_buckets": [ + "additional" + ], + "rationale": "This exact practice-exam question is already available as a selectable exam snippet in the builder.", + "ai_summary_would_help": false, + "ai_summary_note": "" + }, + { + "question_number": 3, + "question_summary": "What will be printed by the following code segment?", + "score": 3, + "evidence_item_ids": [ + "exam-Test Resit - Introduction to Python - 22/23-3-w1-objects-and-names" + ], + "evidence_topics": [ + "Objects and Names" + ], + "evidence_buckets": [ + "additional" + ], + "rationale": "This exact practice-exam question is already available as a selectable exam snippet in the builder.", + "ai_summary_would_help": false, + "ai_summary_note": "" + }, + { + "question_number": 4, + "question_summary": "Suppose you have the following function, which takes two integers as arguments: What will be printed by the following line of code: print(main(1))", + "score": 3, + "evidence_item_ids": [ + "exam-Test Resit - Introduction to Python - 22/23-4-w2-loops" + ], + "evidence_topics": [ + "Loops" + ], + "evidence_buckets": [ + "additional" + ], + "rationale": "This exact practice-exam question is already available as a selectable exam snippet in the builder.", + "ai_summary_would_help": false, + "ai_summary_note": "" + }, + { + "question_number": 5, + "question_summary": "Suppose you have a list called x, where: Which of the following code segments will print the following list? [5, 4, 3, 2, 1]", + "score": 3, + "evidence_item_ids": [ + "exam-Test Resit - Introduction to Python - 22/23-5-w2-lists-and-sets" + ], + "evidence_topics": [ + "Lists and Sets" + ], + "evidence_buckets": [ + "additional" + ], + "rationale": "This exact practice-exam question is already available as a selectable exam snippet in the builder.", + "ai_summary_would_help": false, + "ai_summary_note": "" + }, + { + "question_number": 6, + "question_summary": "You need to write a function called main which accepts a flexible number of keyword arguments. The function should compute and return the sum of the values of the arguments. For ex", + "score": 3, + "evidence_item_ids": [ + "exam-Test Resit - Introduction to Python - 22/23-6-w3-arguments" + ], + "evidence_topics": [ + "Arguments" + ], + "evidence_buckets": [ + "additional" + ], + "rationale": "This exact practice-exam question is already available as a selectable exam snippet in the builder.", + "ai_summary_would_help": false, + "ai_summary_note": "" + } + ] + }, + { + "exam_id": "resit-solutions-for-introduction-to-python-35761538", + "question_count_found": 7, + "question_pages_used": [], + "questions": [ + { + "question_number": 1, + "question_summary": "Suppose you have a list called x containing tuples. Which of the following lines of code will print True?", + "score": 3, + "evidence_item_ids": [ + "exam-Resit 22/23-1-w2-lists-and-sets" + ], + "evidence_topics": [ + "Lists and Sets" + ], + "evidence_buckets": [ + "additional" + ], + "rationale": "This exact practice-exam question is already available as a selectable exam snippet in the builder.", + "ai_summary_would_help": false, + "ai_summary_note": "" + }, + { + "question_number": 2, + "question_summary": "Executing the following program will produce an error. Why?", + "score": 3, + "evidence_item_ids": [ + "exam-Resit 22/23-2-w3-scope" + ], + "evidence_topics": [ + "Scope" + ], + "evidence_buckets": [ + "additional" + ], + "rationale": "This exact practice-exam question is already available as a selectable exam snippet in the builder.", + "ai_summary_would_help": false, + "ai_summary_note": "" + }, + { + "question_number": 3, + "question_summary": "What will be printed by the following code segment?", + "score": 3, + "evidence_item_ids": [ + "exam-Resit 22/23-3-w3-return-behavior" + ], + "evidence_topics": [ + "Return Behavior" + ], + "evidence_buckets": [ + "additional" + ], + "rationale": "This exact practice-exam question is already available as a selectable exam snippet in the builder.", + "ai_summary_would_help": false, + "ai_summary_note": "" + }, + { + "question_number": 4, + "question_summary": "Suppose you have the following function, which takes two integers as arguments: What will be printed by the following line of code: print(main(1))", + "score": 3, + "evidence_item_ids": [ + "exam-Resit 22/23-4-w3-arguments" + ], + "evidence_topics": [ + "Arguments" + ], + "evidence_buckets": [ + "additional" + ], + "rationale": "This exact practice-exam question is already available as a selectable exam snippet in the builder.", + "ai_summary_would_help": false, + "ai_summary_note": "" + }, + { + "question_number": 5, + "question_summary": "Suppose you have a list called x. Which of the following code segments will print the following list? [5, 4, 3, 2, 1]", + "score": 3, + "evidence_item_ids": [ + "exam-Resit 22/23-5-w1-functions-and-imports" + ], + "evidence_topics": [ + "Functions and Imports" + ], + "evidence_buckets": [ + "recommended" + ], + "rationale": "This exact practice-exam question is already available as a selectable exam snippet in the builder.", + "ai_summary_would_help": false, + "ai_summary_note": "" + }, + { + "question_number": 6, + "question_summary": "You need to write a function called main which accepts a flexible number of keyword arguments. The function should compute and return the sum of the values of the arguments. For ex", + "score": 3, + "evidence_item_ids": [ + "exam-Resit 22/23-6-w3-arguments" + ], + "evidence_topics": [ + "Arguments" + ], + "evidence_buckets": [ + "additional" + ], + "rationale": "This exact practice-exam question is already available as a selectable exam snippet in the builder.", + "ai_summary_would_help": false, + "ai_summary_note": "" + }, + { + "question_number": 7, + "question_summary": "Assume you already have a list of strings called words. You need to create a dictionary called word_lengths, where the keys are the strings in the list words and the values are the", + "score": 3, + "evidence_item_ids": [ + "exam-Resit 22/23-7-w2-dictionaries-and-mappings" + ], + "evidence_topics": [ + "Dictionaries and Mappings" + ], + "evidence_buckets": [ + "additional" + ], + "rationale": "This exact practice-exam question is already available as a selectable exam snippet in the builder.", + "ai_summary_would_help": false, + "ai_summary_note": "" + } + ] + }, + { + "exam_id": "trial-final-exam-solutions-introduction-to-python-3077951", + "question_count_found": 6, + "question_pages_used": [], + "questions": [ + { + "question_number": 1, + "question_summary": "You'd like to define a class called Vehicle. It should have two attributes: \"name\" and \"mode\", which you want to be initialized at the time of object construction. The \"name\" attri", + "score": 3, + "evidence_item_ids": [ + "exam-Trial final exam Introduction to Python-1-w4-oop-fundamentals" + ], + "evidence_topics": [ + "OOP Fundamentals" + ], + "evidence_buckets": [ + "recommended" + ], + "rationale": "This exact practice-exam question is already available as a selectable exam snippet in the builder.", + "ai_summary_would_help": false, + "ai_summary_note": "" + }, + { + "question_number": 2, + "question_summary": "Take a look at the following class definition. Suppose that we create a Book object and call its add_review method three times, like this: book_1 = Book(\"The Lightning Thief\", \"Ric", + "score": 3, + "evidence_item_ids": [ + "exam-Trial final exam Introduction to Python-2-w4-oop-fundamentals" + ], + "evidence_topics": [ + "OOP Fundamentals" + ], + "evidence_buckets": [ + "recommended" + ], + "rationale": "This exact practice-exam question is already available as a selectable exam snippet in the builder.", + "ai_summary_would_help": false, + "ai_summary_note": "" + }, + { + "question_number": 3, + "question_summary": "Imagine that you have a list called students, which is populated by a number of dictionaries. Each dictionary in the students list has two keys: \"Name\" and \"Grade\". The correspondi", + "score": 3, + "evidence_item_ids": [ + "exam-Trial final exam Introduction to Python-3-w1-objects-and-names" + ], + "evidence_topics": [ + "Objects and Names" + ], + "evidence_buckets": [ + "additional" + ], + "rationale": "This exact practice-exam question is already available as a selectable exam snippet in the builder.", + "ai_summary_would_help": false, + "ai_summary_note": "" + }, + { + "question_number": 4, + "question_summary": "You need to write a function called format_phone_number that formats phone numbers. The output of the function should be a string that represents a 10-digit number. The input argum", + "score": 3, + "evidence_item_ids": [ + "exam-Trial final exam Introduction to Python-4-w3-defining-and-calling-functions" + ], + "evidence_topics": [ + "Defining and Calling Functions" + ], + "evidence_buckets": [ + "additional" + ], + "rationale": "This exact practice-exam question is already available as a selectable exam snippet in the builder.", + "ai_summary_would_help": false, + "ai_summary_note": "" + }, + { + "question_number": 5, + "question_summary": "You have a pandas DataFrame called df. It has a column called \"A\" and a column called \"B\". Both contain numbers. You'd like to create a column called \"C\", which contains the sum of", + "score": 3, + "evidence_item_ids": [ + "exam-Trial final exam Introduction to Python-5-w5-pandas-core-structures" + ], + "evidence_topics": [ + "Pandas Core Structures" + ], + "evidence_buckets": [ + "recommended" + ], + "rationale": "This exact practice-exam question is already available as a selectable exam snippet in the builder.", + "ai_summary_would_help": false, + "ai_summary_note": "" + }, + { + "question_number": 6, + "question_summary": "You have a pandas DataFrame called df that looks like this, when printed: A B C D 1 9.1 9.5 9.0 6.0 2 6.4 8.2 7.5 1.7 3 2.5 5.3 8.8 3.0 4 6.7 3.6 7.2 6.9 5 8.4 1.9 8.2 3.3 6 8.1 8.", + "score": 3, + "evidence_item_ids": [ + "exam-Trial final exam Introduction to Python-6-w5-inspecting-and-selecting-data" + ], + "evidence_topics": [ + "Inspecting and Selecting Data" + ], + "evidence_buckets": [ + "recommended" + ], + "rationale": "This exact practice-exam question is already available as a selectable exam snippet in the builder.", + "ai_summary_would_help": false, + "ai_summary_note": "" + } + ] + } + ] +} \ No newline at end of file diff --git a/tmp/exam_coverage_audit/selectable_items.json b/tmp/exam_coverage_audit/selectable_items.json new file mode 100644 index 0000000..1e553c4 --- /dev/null +++ b/tmp/exam_coverage_audit/selectable_items.json @@ -0,0 +1,7867 @@ +[ + { + "item_id": "manual-comments", + "card_id": "w1-python-basics", + "topic": "Python Basics", + "subtopic_id": "", + "subtopic_title": "", + "item_type": "ai_common_question", + "bucket": "aiQuestions", + "selection_kind": "direct", + "search_text": "How do comments start, and what does Python ignore after `#`?\nEverything after `#` on that logical line is ignored by Python.\nx = 3 # this comment does not execute\nprint(x)" + }, + { + "item_id": "manual-logical-lines", + "card_id": "w1-python-basics", + "topic": "Python Basics", + "subtopic_id": "", + "subtopic_title": "", + "item_type": "ai_common_question", + "bucket": "aiQuestions", + "selection_kind": "direct", + "search_text": "How can one logical line span multiple physical lines?\nUse open brackets or an explicit backslash to continue a statement across lines.\nnumbers = [\n 1,\n 2,\n 3,\n]" + }, + { + "item_id": "kp-1", + "card_id": "w1-python-basics", + "topic": "Python Basics", + "subtopic_id": "w1-python-basics-execution-model", + "subtopic_title": "Execution Model, Logical Lines, and Comments", + "item_type": "key_point", + "bucket": "keyPoints", + "selection_kind": "direct", + "search_text": "Python script is translated line by line into byte code, then byte code is translated into machine code. Writing code must be precise; ambiguities that humans handle fine will cause Python errors." + }, + { + "item_id": "ai-example-1", + "card_id": "w1-python-basics", + "topic": "Python Basics", + "subtopic_id": "w1-python-basics-execution-model", + "subtopic_title": "Execution Model, Logical Lines, and Comments", + "item_type": "ai_example", + "bucket": "aiExamples", + "selection_kind": "direct", + "search_text": "print('Hello World') # Everything after the hashtag is a comment\nprint('Hello World') # Everything after the hashtag is a comment\nHello World" + }, + { + "item_id": "ai-example-2", + "card_id": "w1-python-basics", + "topic": "Python Basics", + "subtopic_id": "w1-python-basics-execution-model", + "subtopic_title": "Execution Model, Logical Lines, and Comments", + "item_type": "ai_example", + "bucket": "aiExamples", + "selection_kind": "direct", + "search_text": "print(_, __, ___)\n#\nprint(_, __, ___)" + }, + { + "item_id": "ai-example-3", + "card_id": "w1-python-basics", + "topic": "Python Basics", + "subtopic_id": "w1-python-basics-execution-model", + "subtopic_title": "Execution Model, Logical Lines, and Comments", + "item_type": "ai_example", + "bucket": "aiExamples", + "selection_kind": "direct", + "search_text": "print('Hello World')\nprint('Hello World')" + }, + { + "item_id": "ai-example-4", + "card_id": "w1-python-basics", + "topic": "Python Basics", + "subtopic_id": "w1-python-basics-execution-model", + "subtopic_title": "Execution Model, Logical Lines, and Comments", + "item_type": "ai_example", + "bucket": "aiExamples", + "selection_kind": "direct", + "search_text": "print(r\"This gives no \\\" error\")\n#\nprint(r\"This gives no \\\" error\")\nprint(r'This gives no \\' error')" + }, + { + "item_id": "ai-example-5", + "card_id": "w1-python-basics", + "topic": "Python Basics", + "subtopic_id": "w1-python-basics-execution-model", + "subtopic_title": "Execution Model, Logical Lines, and Comments", + "item_type": "ai_example", + "bucket": "aiExamples", + "selection_kind": "direct", + "search_text": "line_joining\na = 'Two or more physical lines can be joined' +\\\n ' with the help of backward slashes'\nprint(a)" + }, + { + "item_id": "ai-example-6", + "card_id": "w1-python-basics", + "topic": "Python Basics", + "subtopic_id": "w1-python-basics-execution-model", + "subtopic_title": "Execution Model, Logical Lines, and Comments", + "item_type": "ai_example", + "bucket": "aiExamples", + "selection_kind": "direct", + "search_text": "line_joining\na = ['Two or more physical lines can be joined', \n ' with the help of backward slashes']\nprint(a)" + }, + { + "item_id": "ks-95be7f9418", + "card_id": "w1-python-basics", + "topic": "Python Basics", + "subtopic_id": "", + "subtopic_title": "", + "item_type": "source_lecture", + "bucket": "recommended", + "selection_kind": "source", + "search_text": "Python execution model\nPython script is translated line by line into byte code, then byte code is translated into machine code. Writing code must be precise; ambiguities that humans handle fine will cause Python errors." + }, + { + "item_id": "cs-09e2b215ee", + "card_id": "w1-python-basics", + "topic": "Python Basics", + "subtopic_id": "", + "subtopic_title": "", + "item_type": "source_notebook", + "bucket": "recommended", + "selection_kind": "source", + "search_text": "print('Hello World') # Everything after the hashtag is a comment\nprint('Hello World') # Everything after the hashtag is a comment\nHello World" + }, + { + "item_id": "cs-814a07a136", + "card_id": "w1-python-basics", + "topic": "Python Basics", + "subtopic_id": "", + "subtopic_title": "", + "item_type": "source_notebook", + "bucket": "additional", + "selection_kind": "source", + "search_text": "123*1\n#\n123*1" + }, + { + "item_id": "aiq-1", + "card_id": "w1-objects-and-names", + "topic": "Objects and Names", + "subtopic_id": "", + "subtopic_title": "", + "item_type": "ai_common_question", + "bucket": "aiQuestions", + "selection_kind": "direct", + "search_text": "Which of the following statements is correct? I: Two objects can have different values, while having the same type. II: Two objects can have the same value, while having different types.\nI is correct (e.g. a=1, b=2, both int). II is incorrect \u2014 if two objects have the same value they must have the same type.\nObjects/types" + }, + { + "item_id": "aiq-2", + "card_id": "w1-objects-and-names", + "topic": "Objects and Names", + "subtopic_id": "", + "subtopic_title": "", + "item_type": "ai_common_question", + "bucket": "aiQuestions", + "selection_kind": "direct", + "search_text": "Why does the following code work even though strings are immutable?\nDecide whether the code is rebinding a name or mutating a shared mutable object.\nImmutability/names" + }, + { + "item_id": "aiq-3", + "card_id": "w1-objects-and-names", + "topic": "Objects and Names", + "subtopic_id": "", + "subtopic_title": "", + "item_type": "ai_common_question", + "bucket": "aiQuestions", + "selection_kind": "direct", + "search_text": "Assume you already have a variable called x, which contains a list of integers.\nExpand `range(start, stop, step)` manually; `stop` is excluded and the next value is found by adding `step` each time.\nExam \u2022 trial_midterm \u2022 Q1\nFor example:\nIf x = [1, 2, 4, 8]\nthe program should prints:\n[1, 4, 16, 64].\nA mylist = []\nfor i in x:\nmylist[i] = x[i]**2\nprint(mylist)\nB mylist = [0] * len(x)\nfor i in range(len(x)):\nmylist[i] = x[i]**2\nprint(mylist)" + }, + { + "item_id": "aiq-4", + "card_id": "w1-objects-and-names", + "topic": "Objects and Names", + "subtopic_id": "", + "subtopic_title": "", + "item_type": "ai_common_question", + "bucket": "aiQuestions", + "selection_kind": "direct", + "search_text": "Suppose you have the following function:\nTrace the returned value, not just what gets printed while the function runs.\nExam \u2022 trial_midterm \u2022 Q3\nSuppose you have the following function:\ndef multiply(*args, factor=2):\ntotal = 1\nfor num in args:\ntotal *= num\nreturn total * factor\nWhich of the following functions will return the same values as the function above, if we call the function thrice as follows:\nmultiply(1, 2, factor=3)\nmultiply(3, 4)\nmultiply()\nA def multiply(*args, factor=2):\ntotal = args[0]" + }, + { + "item_id": "aiq-5", + "card_id": "w1-objects-and-names", + "topic": "Objects and Names", + "subtopic_id": "", + "subtopic_title": "", + "item_type": "ai_common_question", + "bucket": "aiQuestions", + "selection_kind": "direct", + "search_text": "Assume you have the following variables:\nDecide whether the code is rebinding a name or mutating a shared mutable object.\nExam \u2022 trial_midterm \u2022 Q4\nAssume you have the following variables:\nx = 3\ny = 3.0\nz = '3'\nWhat will be printed by the following code:\nprint((x != z and x == int(z)) or (x != y and y != z))\nA 3\nB The code will result in an error.\nC False\nD True" + }, + { + "item_id": "aiq-6", + "card_id": "w1-objects-and-names", + "topic": "Objects and Names", + "subtopic_id": "", + "subtopic_title": "", + "item_type": "ai_common_question", + "bucket": "aiQuestions", + "selection_kind": "direct", + "search_text": "Slicing creates a NEW object\nl2=l1 vs l2=l1[:] \u2014 l2=l1 shares the SAME object, slicing creates independent copy" + }, + { + "item_id": "aiq-7", + "card_id": "w1-objects-and-names", + "topic": "Objects and Names", + "subtopic_id": "", + "subtopic_title": "", + "item_type": "ai_common_question", + "bucket": "aiQuestions", + "selection_kind": "direct", + "search_text": "Mutable default argument\ndef f(lst=[]): \u2014 the [] is created ONCE at def time and persists across calls. Fix: use None and create inside function" + }, + { + "item_id": "kp-1", + "card_id": "w1-objects-and-names", + "topic": "Objects and Names", + "subtopic_id": "w1-objects-and-names-core", + "subtopic_title": "Objects, Types, Mutability, Assignment, and Names", + "item_type": "key_point", + "bucket": "keyPoints", + "selection_kind": "direct", + "search_text": "Each object has identity, type, and value. Names bind to objects; rebinding changes the name, while in-place changes only affect mutable objects." + }, + { + "item_id": "kp-2", + "card_id": "w1-objects-and-names", + "topic": "Objects and Names", + "subtopic_id": "w1-objects-and-names-core", + "subtopic_title": "Objects, Types, Mutability, Assignment, and Names", + "item_type": "key_point", + "bucket": "keyPoints", + "selection_kind": "direct", + "search_text": "Immutable types like `int`, `float`, `str`, and `tuple` cannot change in place. Mutable types like `list`, `dict`, and `set` can be changed through the same object." + }, + { + "item_id": "kp-2-d1", + "card_id": "w1-objects-and-names", + "topic": "Objects and Names", + "subtopic_id": "", + "subtopic_title": "", + "item_type": "key_point_detail", + "bucket": "keyPoints", + "selection_kind": "detail", + "search_text": "List is mutable \u2014 can change element in place\nl1 = [1, 2, 3]\nprint(l1) # [1, 2, 3]\nl1[2] = 4\nprint(l1) # [1, 2, 4]" + }, + { + "item_id": "kp-2-d2", + "card_id": "w1-objects-and-names", + "topic": "Objects and Names", + "subtopic_id": "", + "subtopic_title": "", + "item_type": "key_point_detail", + "bucket": "keyPoints", + "selection_kind": "detail", + "search_text": "Tuple is immutable \u2014 assigning to index raises TypeError\nt1 = (1, 2, 3)\nt1[2] = 4\n# TypeError: 'tuple' object does not support item assignment" + }, + { + "item_id": "kp-3", + "card_id": "w1-objects-and-names", + "topic": "Objects and Names", + "subtopic_id": "w1-objects-and-names-core", + "subtopic_title": "Objects, Types, Mutability, Assignment, and Names", + "item_type": "key_point", + "bucket": "keyPoints", + "selection_kind": "direct", + "search_text": "Assignment binds the left-hand name to the object produced on the right-hand side." + }, + { + "item_id": "kp-3-d1", + "card_id": "w1-objects-and-names", + "topic": "Objects and Names", + "subtopic_id": "", + "subtopic_title": "", + "item_type": "key_point_detail", + "bucket": "keyPoints", + "selection_kind": "detail", + "search_text": "Basic assignment\nname_1 = 300\nprint(name_1) # 300\nprint(type(name_1)) # \nprint(id(name_1)) # some unique integer" + }, + { + "item_id": "kp-3-d2", + "card_id": "w1-objects-and-names", + "topic": "Objects and Names", + "subtopic_id": "", + "subtopic_title": "", + "item_type": "key_point_detail", + "bucket": "keyPoints", + "selection_kind": "detail", + "search_text": "Two names bound to the same object (same id)\nname_3 = name_4 = name_5 = name_6 = 300\nprint(name_3 is name_4 is name_5 is name_6) # True" + }, + { + "item_id": "kp-4", + "card_id": "w1-objects-and-names", + "topic": "Objects and Names", + "subtopic_id": "w1-objects-and-names-core", + "subtopic_title": "Objects, Types, Mutability, Assignment, and Names", + "item_type": "key_point", + "bucket": "keyPoints", + "selection_kind": "direct", + "search_text": "Core built-in types: `int`, `float`, `str`, `bool`, `tuple`, `list`, `dict`, `set`." + }, + { + "item_id": "kp-4-d1", + "card_id": "w1-objects-and-names", + "topic": "Objects and Names", + "subtopic_id": "", + "subtopic_title": "", + "item_type": "key_point_detail", + "bucket": "keyPoints", + "selection_kind": "detail", + "search_text": "All 8 types\nvar_1 = 123 # int\nvar_2 = 123.3 # float\nvar_3 = '123' # str\nvar_4 = True # bool\nvar_5 = ('123', 123) # tuple\nvar_6 = [123, '123'] # list\nvar_7 = {'k1': 'v1'} # dict\nvar_8 = {123, '123'} # set" + }, + { + "item_id": "kp-5", + "card_id": "w1-objects-and-names", + "topic": "Objects and Names", + "subtopic_id": "w1-objects-and-names-core", + "subtopic_title": "Objects, Types, Mutability, Assignment, and Names", + "item_type": "key_point", + "bucket": "keyPoints", + "selection_kind": "direct", + "search_text": "Names can consist of letters (upper/lower), digits, and underscores. Names CANNOT start with a digit. Names ARE case-sensitive (name_1 != Name_1). Avoid Python reserved words (e.g., don't name a variable 'sorted', 'list', 'print')." + }, + { + "item_id": "kp-6", + "card_id": "w1-objects-and-names", + "topic": "Objects and Names", + "subtopic_id": "w1-objects-and-names-core", + "subtopic_title": "Objects, Types, Mutability, Assignment, and Names", + "item_type": "key_point", + "bucket": "keyPoints", + "selection_kind": "direct", + "search_text": "Syntax: seq[start:end:step]. Start is inclusive, end is NOT inclusive. Defaults: start=0, end=len, step=1. Negative step goes from right to left. Slicing always creates a NEW object of the same type." + }, + { + "item_id": "kp-6-d1", + "card_id": "w1-objects-and-names", + "topic": "Objects and Names", + "subtopic_id": "", + "subtopic_title": "", + "item_type": "key_point_detail", + "bucket": "keyPoints", + "selection_kind": "detail", + "search_text": "Basic slicing examples\nl1 = [1, 2, 3, 4, 5, 6, 7, 8]\nprint(l1[7]) # 8\nprint(l1[-1]) # 8\nprint(l1[-5:5]) # [4, 5]\nprint(l1[:-5]) # [1, 2, 3]" + }, + { + "item_id": "kp-6-d2", + "card_id": "w1-objects-and-names", + "topic": "Objects and Names", + "subtopic_id": "", + "subtopic_title": "", + "item_type": "key_point_detail", + "bucket": "keyPoints", + "selection_kind": "detail", + "search_text": "Negative step\nl1 = [1, 2, 3, 4, 5, 6, 7, 8]\nprint(l1[5:1:-2]) # [6, 4]\nprint(l1[5::-1]) # [6, 5, 4, 3, 2, 1]\nprint(l1[:1:-1]) # [8, 7, 6, 5, 4, 3]\nprint(l1[1:5:-2]) # [] (already past end)" + }, + { + "item_id": "kp-7", + "card_id": "w1-objects-and-names", + "topic": "Objects and Names", + "subtopic_id": "w1-objects-and-names-core", + "subtopic_title": "Objects, Types, Mutability, Assignment, and Names", + "item_type": "key_point", + "bucket": "keyPoints", + "selection_kind": "direct", + "search_text": "Functions are objects. Defined with def. Called with (). Built-in functions: print, id, len, type, del. Functions can return values. Methods are functions attached to objects." + }, + { + "item_id": "kp-7-d1", + "card_id": "w1-objects-and-names", + "topic": "Objects and Names", + "subtopic_id": "", + "subtopic_title": "", + "item_type": "key_point_detail", + "bucket": "keyPoints", + "selection_kind": "detail", + "search_text": "Simple function\ndef size(length, width):\n return length * width\nprint(size(2,3)) # 6" + }, + { + "item_id": "kp-8", + "card_id": "w1-objects-and-names", + "topic": "Objects and Names", + "subtopic_id": "w1-objects-and-names-core", + "subtopic_title": "Objects, Types, Mutability, Assignment, and Names", + "item_type": "key_point", + "bucket": "keyPoints", + "selection_kind": "direct", + "search_text": "Which code fragment will print the following output? / What will be printed by the following code fragment? / Which code fragment prints the SAME output as...? / One fragment prints different output from the others." + }, + { + "item_id": "kp-9", + "card_id": "w1-objects-and-names", + "topic": "Objects and Names", + "subtopic_id": "w1-objects-and-names-core", + "subtopic_title": "Objects, Types, Mutability, Assignment, and Names", + "item_type": "key_point", + "bucket": "keyPoints", + "selection_kind": "direct", + "search_text": "Everything in Python is an object. Objects in Python have one id, one value, one type, and zero or more names An assignment statement is one of the ways to create an object. An object created with an assignment statement will have a name, an id, a value and a type." + }, + { + "item_id": "ai-example-1", + "card_id": "w1-objects-and-names", + "topic": "Objects and Names", + "subtopic_id": "w1-objects-and-names-core", + "subtopic_title": "Objects, Types, Mutability, Assignment, and Names", + "item_type": "ai_example", + "bucket": "aiExamples", + "selection_kind": "direct", + "search_text": "List is mutable \u2014 can change element in place\nl1 = [1, 2, 3]\nprint(l1) # [1, 2, 3]\nl1[2] = 4\nprint(l1) # [1, 2, 4]\nImmutable types like `int`, `float`, `str`, and `tuple` cannot change in place. Mutable types like `list`, `dict`, and `set` can be changed through the same object." + }, + { + "item_id": "ai-example-2", + "card_id": "w1-objects-and-names", + "topic": "Objects and Names", + "subtopic_id": "w1-objects-and-names-core", + "subtopic_title": "Objects, Types, Mutability, Assignment, and Names", + "item_type": "ai_example", + "bucket": "aiExamples", + "selection_kind": "direct", + "search_text": "Tuple is immutable \u2014 assigning to index raises TypeError\nt1 = (1, 2, 3)\nt1[2] = 4\n# TypeError: 'tuple' object does not support item assignment\nImmutable types like `int`, `float`, `str`, and `tuple` cannot change in place. Mutable types like `list`, `dict`, and `set` can be changed through the same object." + }, + { + "item_id": "ai-example-3", + "card_id": "w1-objects-and-names", + "topic": "Objects and Names", + "subtopic_id": "w1-objects-and-names-core", + "subtopic_title": "Objects, Types, Mutability, Assignment, and Names", + "item_type": "ai_example", + "bucket": "aiExamples", + "selection_kind": "direct", + "search_text": "Basic assignment\nname_1 = 300\nprint(name_1) # 300\nprint(type(name_1)) # \nprint(id(name_1)) # some unique integer\nAssignment binds the left-hand name to the object produced on the right-hand side." + }, + { + "item_id": "ai-example-4", + "card_id": "w1-objects-and-names", + "topic": "Objects and Names", + "subtopic_id": "w1-objects-and-names-core", + "subtopic_title": "Objects, Types, Mutability, Assignment, and Names", + "item_type": "ai_example", + "bucket": "aiExamples", + "selection_kind": "direct", + "search_text": "Two names bound to the same object (same id)\nname_3 = name_4 = name_5 = name_6 = 300\nprint(name_3 is name_4 is name_5 is name_6) # True\nAssignment binds the left-hand name to the object produced on the right-hand side." + }, + { + "item_id": "ai-example-5", + "card_id": "w1-objects-and-names", + "topic": "Objects and Names", + "subtopic_id": "w1-objects-and-names-core", + "subtopic_title": "Objects, Types, Mutability, Assignment, and Names", + "item_type": "ai_example", + "bucket": "aiExamples", + "selection_kind": "direct", + "search_text": "All 8 types\nvar_1 = 123 # int\nvar_2 = 123.3 # float\nvar_3 = '123' # str\nvar_4 = True # bool\nvar_5 = ('123', 123) # tuple\nvar_6 = [123, '123'] # list\nvar_7 = {'k1': 'v1'} # dict\nvar_8 = {123, '123'} # set\nCore built-in types: `int`, `float`, `str`, `bool`, `tuple`, `list`, `dict`, `set`." + }, + { + "item_id": "ai-example-6", + "card_id": "w1-objects-and-names", + "topic": "Objects and Names", + "subtopic_id": "w1-objects-and-names-core", + "subtopic_title": "Objects, Types, Mutability, Assignment, and Names", + "item_type": "ai_example", + "bucket": "aiExamples", + "selection_kind": "direct", + "search_text": "Basic slicing examples\nl1 = [1, 2, 3, 4, 5, 6, 7, 8]\nprint(l1[7]) # 8\nprint(l1[-1]) # 8\nprint(l1[-5:5]) # [4, 5]\nprint(l1[:-5]) # [1, 2, 3]\nSyntax: seq[start:end:step]. Start is inclusive, end is NOT inclusive. Defaults: start=0, end=len, step=1. Negative step goes from right to left. Slicing always creates a NEW object of the same type." + }, + { + "item_id": "ai-example-7", + "card_id": "w1-objects-and-names", + "topic": "Objects and Names", + "subtopic_id": "w1-objects-and-names-core", + "subtopic_title": "Objects, Types, Mutability, Assignment, and Names", + "item_type": "ai_example", + "bucket": "aiExamples", + "selection_kind": "direct", + "search_text": "Negative step\nl1 = [1, 2, 3, 4, 5, 6, 7, 8]\nprint(l1[5:1:-2]) # [6, 4]\nprint(l1[5::-1]) # [6, 5, 4, 3, 2, 1]\nprint(l1[:1:-1]) # [8, 7, 6, 5, 4, 3]\nprint(l1[1:5:-2]) # [] (already past end)\nSyntax: seq[start:end:step]. Start is inclusive, end is NOT inclusive. Defaults: start=0, end=len, step=1. Negative step goes from right to left. Slicing always creates a NEW object of the same type." + }, + { + "item_id": "ai-example-8", + "card_id": "w1-objects-and-names", + "topic": "Objects and Names", + "subtopic_id": "w1-objects-and-names-core", + "subtopic_title": "Objects, Types, Mutability, Assignment, and Names", + "item_type": "ai_example", + "bucket": "aiExamples", + "selection_kind": "direct", + "search_text": "Simple function\ndef size(length, width):\n return length * width\nprint(size(2,3)) # 6\nFunctions are objects. Defined with def. Called with (). Built-in functions: print, id, len, type, del. Functions can return values. Methods are functions attached to objects." + }, + { + "item_id": "exam-intro_python_sample_final_24_25-13-w1-objects-and-names", + "card_id": "w1-objects-and-names", + "topic": "Objects and Names", + "subtopic_id": "", + "subtopic_title": "", + "item_type": "source_exam", + "bucket": "recommended", + "selection_kind": "source", + "search_text": "What are the outputs of the following lines of code? print(x == y), print(y == z), print(x == z), print(x == y == z)\nA\nB\nC\nD\nA\n'3' == 3 is False. 3 == 3.0 is True. '3' == 3.0 is False. x == y == z evaluates as (x == y) and (y == z), which is False and True, resulting in False." + }, + { + "item_id": "exam-trial-final-exam-py22-1-w1-objects-and-names", + "card_id": "w1-objects-and-names", + "topic": "Objects and Names", + "subtopic_id": "", + "subtopic_title": "", + "item_type": "source_exam", + "bucket": "recommended", + "selection_kind": "source", + "search_text": "Suppose you have a variable called x which contains an integer between 0 and 10 (both are inclusive).\n\nWhich of the following programs will tell you whether x contains an odd or even number?\na\nb\nc\nd\nd\nAll three programs correctly identify whether x is odd or even for integers between 0 and 10." + }, + { + "item_id": "exam-Test Resit - Introduction to Python - 22/23-3-w1-objects-and-names", + "card_id": "w1-objects-and-names", + "topic": "Objects and Names", + "subtopic_id": "", + "subtopic_title": "", + "item_type": "source_exam", + "bucket": "recommended", + "selection_kind": "source", + "search_text": "What will be printed by the following code segment?\na\nb\nc\nd\nb\nThe type of x is a list. The loop checks if the type of each element is equal to the type of x. The only element in x that is a list is the empty list `[]`. Thus, `[[]]` is returned." + }, + { + "item_id": "exam-Trial final - Introduction to Python - 22/23-1-w1-objects-and-names", + "card_id": "w1-objects-and-names", + "topic": "Objects and Names", + "subtopic_id": "", + "subtopic_title": "", + "item_type": "source_exam", + "bucket": "recommended", + "selection_kind": "source", + "search_text": "Suppose you already have: (i) a list of strings called europe which contain the names of all European countries, and (ii) a string variable called destination.\n\nYou want to write a program to advice Dutch residents on the documents they need to prepare before traveling:\nIf they travel within Europe, your program should print \"No passport needed. Bring your ID card.\"\nIf they travel outside of Europe, the program should print \"Please bring your passport.\"\n\nWhich of the following code segment will achieve what you need?\na\nb\nc\nd\na\nOption A correctly checks if destination is in the list 'europe' using the 'in' operator, and uses 'print' as requested. Option B uses 'return' which is only valid inside a function, and the prompt doesn't mention a function. Option C uses an assignment operator '=' instead of '==' and iterates incorrectly. Option D iterates incorrectly and uses 'return'." + }, + { + "item_id": "exam-Trial final exam Introduction to Python-3-w1-objects-and-names", + "card_id": "w1-objects-and-names", + "topic": "Objects and Names", + "subtopic_id": "", + "subtopic_title": "", + "item_type": "source_exam", + "bucket": "recommended", + "selection_kind": "source", + "search_text": "Imagine that you have a list called students, which is populated by a number of dictionaries.\n\nEach dictionary in the students list has two keys: \"Name\" and \"Grade\". The corresponding values are student names (as strings) and course grades (as floats).\n\nFor each student, you'd like to print the following text to the screen:\n[NAME] has received a grade of [GRADE].\nwhere [NAME] is substituted by the name of the student and [GRADE] is substituted by the actual course grade. The course grade should be displayed to one decimal place after the decimal point.\n\nFor example, if\nstudents = [{\"Name\": \"Adam\", \"Grade\": 7.5}, {\"Name\": \"Bernard\", \"Grade\": 8.0}]\nthen you'd like to see the following two lines printed to the screen:\nAdam has received a grade of 7.5.\nBernard has received a grade of 8.0.\n\nWhich of the following code segments will achieve what you want?\na\nb\nc\nd\na\nOption A correctly iterates over the list of dictionaries and uses f-strings with proper quote escaping (single quotes inside double quotes) and the `:.1f` format specifier to display the float to one decimal place." + }, + { + "item_id": "exam-trial_midterm-1-w1-objects-and-names", + "card_id": "w1-objects-and-names", + "topic": "Objects and Names", + "subtopic_id": "", + "subtopic_title": "", + "item_type": "source_exam", + "bucket": "recommended", + "selection_kind": "source", + "search_text": "Assume you already have a variable called x, which contains a list of integers.\nWhich of the following programs will print you a list of the squared values of the elements in x?" + }, + { + "item_id": "exam-trial_midterm-3-w1-objects-and-names", + "card_id": "w1-objects-and-names", + "topic": "Objects and Names", + "subtopic_id": "", + "subtopic_title": "", + "item_type": "source_exam", + "bucket": "recommended", + "selection_kind": "source", + "search_text": "Suppose you have the following function:\ndef multiply(*args, factor=2):\ntotal = 1\nfor num in args:\ntotal *= num\nreturn total * factor\nWhich of the following functions will return the same values as the function above, if we call the function thrice as follows:\nmultiply(1, 2, factor=3)\nmultiply(3, 4)\nmultiply()\nA def multiply(*args, factor=2):\ntotal = args[0]\nfor num in args:\ntotal *= num\nreturn total * factor\nB def multiply(*args, factor=2):\nif not args:\nreturn 0\ntotal = args[0]\nfor num in args[1:]:\ntotal *= num\nreturn total * factor\nC Both functions will return the same values.\nD Neither functions will return the same values." + }, + { + "item_id": "exam-trial_midterm-4-w1-objects-and-names", + "card_id": "w1-objects-and-names", + "topic": "Objects and Names", + "subtopic_id": "", + "subtopic_title": "", + "item_type": "source_exam", + "bucket": "recommended", + "selection_kind": "source", + "search_text": "Assume you have the following variables:\nx = 3\ny = 3.0\nz = '3'\nWhat will be printed by the following code:\nprint((x != z and x == int(z)) or (x != y and y != z))\nA 3\nB The code will result in an error.\nC False\nD True" + }, + { + "item_id": "exam-trial_midterm-7-w1-objects-and-names", + "card_id": "w1-objects-and-names", + "topic": "Objects and Names", + "subtopic_id": "", + "subtopic_title": "", + "item_type": "source_exam", + "bucket": "recommended", + "selection_kind": "source", + "search_text": "You need to write a function called dict_keys that checks whether a certain key is in available in a certain dictionary." + }, + { + "item_id": "ks-e88d0a8060", + "card_id": "w1-objects-and-names", + "topic": "Objects and Names", + "subtopic_id": "", + "subtopic_title": "", + "item_type": "source_lecture", + "bucket": "recommended", + "selection_kind": "source", + "search_text": "Objects: core properties\nEvery object has exactly one unique id (cannot change), exactly one type (cannot change), and exactly one value. The type defines what value can be stored and whether the value is mutable or immutable. An object can have zero, one, or more names bound to it. A name can only refer to one object at any time." + }, + { + "item_id": "ks-eae9bf47dd", + "card_id": "w1-objects-and-names", + "topic": "Objects and Names", + "subtopic_id": "", + "subtopic_title": "", + "item_type": "source_lecture", + "bucket": "recommended", + "selection_kind": "source", + "search_text": "Mutable vs immutable types\nImmutable: int, float, str, bool, tuple. Mutable: list, dict, set. The value of a mutable object CAN be changed in-place. The value of an immutable object CANNOT be changed \u2014 a new object must be created.\nList is mutable \u2014 can change element in place\nl1 = [1, 2, 3]\nprint(l1) # [1, 2, 3]\nl1[2] = 4\nprint(l1) # [1, 2, 4]\nTuple is immutable \u2014 assigning to index raises TypeError\nt1 = (1, 2, 3)\nt1[2] = 4\n# TypeError: 'tuple' object does not support item assignment\nString reassignment creates a NEW object, not mutation\nbox_1 = 'content'\nold_id = id(box_1)\nbox_1 = 'new content'\nnew_id = id(box_1)\nprint(old_id == new_id) # False \u2014 different object" + }, + { + "item_id": "ks-61c5deec4a", + "card_id": "w1-objects-and-names", + "topic": "Objects and Names", + "subtopic_id": "", + "subtopic_title": "", + "item_type": "source_lecture", + "bucket": "recommended", + "selection_kind": "source", + "search_text": "Assignment statements \u2014 reading right to left\nPython creates a new object with the value on the right, infers type from the value, then binds the name on the left to that object.\nBasic assignment\nname_1 = 300\nprint(name_1) # 300\nprint(type(name_1)) # \nprint(id(name_1)) # some unique integer\nTwo names bound to the same object (same id)\nname_3 = name_4 = name_5 = name_6 = 300\nprint(name_3 is name_4 is name_5 is name_6) # True\nTwo separate objects with equal value (different id)\nname_1 = 300\nname_2 = 300\nprint(name_1 == name_2) # True (same value)\nprint(id(name_1) != id(name_2)) # True (different objects)" + }, + { + "item_id": "ks-cb3a9e3fd2", + "card_id": "w1-objects-and-names", + "topic": "Objects and Names", + "subtopic_id": "", + "subtopic_title": "", + "item_type": "source_lecture", + "bucket": "recommended", + "selection_kind": "source", + "search_text": "Object types \u2014 the 8 types to know\nint, float, str, bool, tuple, list, dict, set\nAll 8 types\nvar_1 = 123 # int\nvar_2 = 123.3 # float\nvar_3 = '123' # str\nvar_4 = True # bool\nvar_5 = ('123', 123) # tuple\nvar_6 = [123, '123'] # list\nvar_7 = {'k1': 'v1'} # dict\nvar_8 = {123, '123'} # set" + }, + { + "item_id": "exam-trial_midterm-9-w1-objects-and-names", + "card_id": "w1-objects-and-names", + "topic": "Objects and Names", + "subtopic_id": "", + "subtopic_title": "", + "item_type": "source_exam", + "bucket": "additional", + "selection_kind": "source", + "search_text": "Consider the following code snippet:\nmylist = [1, 2, 5, 7, 9, 12]\nnew_list1 = mylist[0:3]\nnew_list2 = mylist[1:4]\nprint(new_list1 + new_list2)\nWhat will be printed?\nA [1, 2, 5, 7, 2, 5, 7, 9]\nB [1, 2, 5, 2, 5, 7]\nC [2, 5, 7, 5, 7, 9]\nD [2, 5, 5, 7]" + }, + { + "item_id": "exam-trial_midterm-11-w1-objects-and-names", + "card_id": "w1-objects-and-names", + "topic": "Objects and Names", + "subtopic_id": "", + "subtopic_title": "", + "item_type": "source_exam", + "bucket": "additional", + "selection_kind": "source", + "search_text": "Consider the following code snippet:\nx = 10\ny = '5'\nz = x + y\n\u200bWhat will be the value of 'z' and why?\nA The code will result in a None because 'x' and 'y' have different types.\nB The code will result in an error because you can't add an integer and a string together.\nC The value of z will be '105' because Python concatenates strings.\nD The value of z will be 15 because the string '5' will be implicitly converted to an integer." + }, + { + "item_id": "exam-trial_midterm-12-w1-objects-and-names", + "card_id": "w1-objects-and-names", + "topic": "Objects and Names", + "subtopic_id": "", + "subtopic_title": "", + "item_type": "source_exam", + "bucket": "additional", + "selection_kind": "source", + "search_text": "Which other program will produce the same output as the following code snippet?" + }, + { + "item_id": "exam-trial_midterm-14-w1-objects-and-names", + "card_id": "w1-objects-and-names", + "topic": "Objects and Names", + "subtopic_id": "", + "subtopic_title": "", + "item_type": "source_exam", + "bucket": "additional", + "selection_kind": "source", + "search_text": "Consider the following code snippet:\na = 1\nb = 2.0\nc = '3'\nd = 'hello'\ny = {}\nfor i in [0,1]:\nif i==0:\nif type(a)==type(b):\ny[i] = True\nelse:\ny[i] = False\nif i==1:\nif type(c)==type(d):\ny[i] = True\nelse:\ny[i] = False\nprint(y)\nWhat will this code snippet print?\nA {0: 1, 1: 1}\nB {0: True, 1: True}\nC {0: 0, 1: 1}\nD {0: False, 1: True}" + }, + { + "item_id": "exam-trial_midterm-15-w1-objects-and-names", + "card_id": "w1-objects-and-names", + "topic": "Objects and Names", + "subtopic_id": "", + "subtopic_title": "", + "item_type": "source_exam", + "bucket": "additional", + "selection_kind": "source", + "search_text": "Suppose you have the following function count_characters, which takes two arguments:\na list of strings which are names, and\nan optional keyword argument called character that has a default value of 'a'.\ndef count_character(x, character='a'):\ny = {}\nfor key in x:\ncount = 0\nfor char in key:\nif char == character:\ncount += 1\ny[key] = count\nreturn y\nWhat would be returned by this function, if we call the function twice as follows:\ncount_character(['Emma', 'Julia', 'Ian', 'Noah', 'Liam', 'Anna'], 'i')\ncount_character(['Emma', 'Julia', 'Ian', 'Noah', 'Liam', 'Anna'])\nA {'Emma': 0, 'Julia': 1, 'Ian': 0, 'Noah': 0, 'Liam': 1, 'Anna': 0}\n{'Emma': 1, 'Julia': 1, 'Ian': 1, 'Noah': 1, 'Liam': 1, 'Anna': 1}\nB The first function call will result in an error because there are too many arguments.\nC The second function call will result in an error because there is a missing argument.\nD {'Emma': 0, 'Julia': 1, 'Ian': 0, 'Noah': 0, 'Liam': 1, 'Anna': 0}\n{'Emma': 0, 'Julia': 0, 'Ian': 0, 'Noah': 0, 'Liam': 0, 'Anna': 0}" + }, + { + "item_id": "exam-trial_midterm-16-w1-objects-and-names", + "card_id": "w1-objects-and-names", + "topic": "Objects and Names", + "subtopic_id": "", + "subtopic_title": "", + "item_type": "source_exam", + "bucket": "additional", + "selection_kind": "source", + "search_text": "What is the output of the program below?" + }, + { + "item_id": "exam-trial_midterm-18-w1-objects-and-names", + "card_id": "w1-objects-and-names", + "topic": "Objects and Names", + "subtopic_id": "", + "subtopic_title": "", + "item_type": "source_exam", + "bucket": "additional", + "selection_kind": "source", + "search_text": "Suppose you have the following function which take a list of numerical strings as an argument." + }, + { + "item_id": "exam-trial_midterm-20-w1-objects-and-names", + "card_id": "w1-objects-and-names", + "topic": "Objects and Names", + "subtopic_id": "", + "subtopic_title": "", + "item_type": "source_exam", + "bucket": "additional", + "selection_kind": "source", + "search_text": "You have the following list:\nmy_list = [1,2,3,4]\nWhich one of the following lines of code lines does not print 4 as the output?\nA print(my_list[4])\nB print(my_list[-1])\nC print(max(my_list))\nD print(len(my_list))" + }, + { + "item_id": "exam-trial_midterm-21-w1-objects-and-names", + "card_id": "w1-objects-and-names", + "topic": "Objects and Names", + "subtopic_id": "", + "subtopic_title": "", + "item_type": "source_exam", + "bucket": "additional", + "selection_kind": "source", + "search_text": "Consider the following code snippet:\nx = [\"a\", \"b\", \"c\", \"4\"]\nprint(x[-3] + x[3]*3)\nWhich of the following code snippet will print the same output?\nA y = [1, 2, 3, 4]\nprint('b'+ max(y)*3)\nB print('b' + str(len(x)*3))\nC z = [[\"a\", \"b\", \"c\"], [1, 2, 3, 4]]\nprint(z[0][1] + str(z[1][3])*3)\nD print('b'+ str(8 % 4)*3)" + }, + { + "item_id": "exam-trial_midterm-22-w1-objects-and-names", + "card_id": "w1-objects-and-names", + "topic": "Objects and Names", + "subtopic_id": "", + "subtopic_title": "", + "item_type": "source_exam", + "bucket": "additional", + "selection_kind": "source", + "search_text": "Suppose you have the following a dictionary called students, which contains three sub-dictionaries:\nstudents = {\"james\": {\"name\": \"James\",\n\"homework\": [90.0, 97.0, 75.0, 92.0],\n\"quizzes\": [88.0, 40.0, 94.0],\n\"tests\": [75.0, 90.0]},\n\"eva\": {\"name\": \"Eva\",\n\"homework\": [100.0, 92.0, 98.0, 100.0],\n\"quizzes\": [82.0, 83.0, 91.0],\n\"tests\": [89.0, 97.0]},\n\"david\": {\"name\": \"David\",\n\"homework\": [0.0, 87.0, 75.0, 22.0],\n\"quizzes\": [0.0, 75.0, 78.0],\n\"tests\": [100.0, 100.0]}\n}\nYou want to create a function that calculates the average final course grade of a student.\nThe final course grade is calculated as 20% average homework grade, 10% average quizzes grade and 70% average tests\ngrade.\nWhich of the following programs will work as intended and will give the final course grade of Eva?\nA def average(numbers):\nreturn sum(numbers)/(len(numbers))\ndef final_average(student):\nhomework = average(student['homework'])\nquizzes = average(student['quizzes'])\ntests = average(student['tests'])\nreturn round(0.2*homework + 0.1*quizzes + 0.7*tests, 2)\nfinal_average(students[\"eva\"])\nB def final_average(student):\ndef average(numbers):\nreturn sum(numbers)/(len(numbers)\nhomework = average(student['homework'])\nq\u2026" + }, + { + "item_id": "exam-trial_midterm-24-w1-objects-and-names", + "card_id": "w1-objects-and-names", + "topic": "Objects and Names", + "subtopic_id": "", + "subtopic_title": "", + "item_type": "source_exam", + "bucket": "additional", + "selection_kind": "source", + "search_text": "Consider the following code snippet:\na = True\nb = False\nc = True\nd = False\nif not (a or b) and (c or d):\nprint(\"True\")\nelse:\nprint(\"False\")\nWhat will be printed by the code?\nA The code will result in an error.\nB True\nC None\nD False\nEnd of test Trial Midterm - Introduction to Python - 23/24" + }, + { + "item_id": "exam-midterm_2023-4-w1-objects-and-names", + "card_id": "w1-objects-and-names", + "topic": "Objects and Names", + "subtopic_id": "", + "subtopic_title": "", + "item_type": "source_exam", + "bucket": "additional", + "selection_kind": "source", + "search_text": "Assume you have the following variables:\nx = 'abc'\ny = 3\nz = 2.0\nWhat will be printed after these lines of code?\nprint(x*y)\nprint(x*z)\nprint(y*z)\nA 'abcabcabc'\nThe code will result in a TypeError because you can't multiply a float and a string together.\n6.0\nB The code will result in a ValueError because you can't concatenate a string and an integer.\nThe code will result in a TypeError because you can't multiply a float and a string together.\n6\nC 'abcabcabc'\n'abcabc'\n6.0\nD 'abcabcabc'\nThe code will result in a TypeError because you can't multiply a float and a string together.\n6" + }, + { + "item_id": "exam-midterm_2024-4-w1-objects-and-names", + "card_id": "w1-objects-and-names", + "topic": "Objects and Names", + "subtopic_id": "", + "subtopic_title": "", + "item_type": "source_exam", + "bucket": "additional", + "selection_kind": "source", + "search_text": "Consider the following code snippet:\na = 1\nb = 2.0\nc = '3'\nd = 'hello'\ny = {}\nfor i in [0,1]:\nif i==0:\nif type(a)==type(b):\ny[i] = True\nelse:\ny[i] = False\nif i==1:\nif type(c)==type(d):\ny[i] = True\nelse:\ny[i] = False\nprint(y)\nWhat will this code snippet print?\nA {0: False, 1: True}\nB {0: True, 1: True}\nC {0: 0, 1: 1}\nD {0: 1, 1: 1}" + }, + { + "item_id": "exam-midterm_2024-6-w1-objects-and-names", + "card_id": "w1-objects-and-names", + "topic": "Objects and Names", + "subtopic_id": "", + "subtopic_title": "", + "item_type": "source_exam", + "bucket": "additional", + "selection_kind": "source", + "search_text": "Consider the following code snippet:\nx = 10\ny = '5'\nz = x + y\n\u200bWhat will be the value of 'z' and why?\nA The value of z will be 15 because the string '5' will be implicitly converted to an integer.\nB The value of z will be '105' because Python concatenates strings.\nC The code will result in an error because you can't add an integer and a string together.\nD The code will result in a None because 'x' and 'y' have different types." + }, + { + "item_id": "exam-extra_practice-11-w1-objects-and-names", + "card_id": "w1-objects-and-names", + "topic": "Objects and Names", + "subtopic_id": "", + "subtopic_title": "", + "item_type": "source_exam", + "bucket": "additional", + "selection_kind": "source", + "search_text": "x = ['abc', [[]], (1, 2), {}, True, 3.0, 4]\n\nWhat is the output of the following code snippet?\n\nprint(type(float(x[2][0] + x[2][1])) == type(x[-2]))\na\nb\nc\nd\nd\nx[2] = (1,2). x[2][0]=1, x[2][1]=2. 1+2=3. float(3)=3.0. type(3.0)=float. x[-2]=3.0 (index 5). type(3.0)=float. float==float \u2192 True." + }, + { + "item_id": "ks-d79a1899f6", + "card_id": "w1-objects-and-names", + "topic": "Objects and Names", + "subtopic_id": "", + "subtopic_title": "", + "item_type": "source_lecture", + "bucket": "additional", + "selection_kind": "source", + "search_text": "Names / variable naming rules\nNames can consist of letters (upper/lower), digits, and underscores. Names CANNOT start with a digit. Names ARE case-sensitive (name_1 != Name_1). Avoid Python reserved words (e.g., don't name a variable 'sorted', 'list', 'print')." + }, + { + "item_id": "ks-6f41148083", + "card_id": "w1-objects-and-names", + "topic": "Objects and Names", + "subtopic_id": "", + "subtopic_title": "", + "item_type": "source_lecture", + "bucket": "additional", + "selection_kind": "source", + "search_text": "Slicing\nSyntax: seq[start:end:step]. Start is inclusive, end is NOT inclusive. Defaults: start=0, end=len, step=1. Negative step goes from right to left. Slicing always creates a NEW object of the same type.\nBasic slicing examples\nl1 = [1, 2, 3, 4, 5, 6, 7, 8]\nprint(l1[7]) # 8\nprint(l1[-1]) # 8\nprint(l1[-5:5]) # [4, 5]\nprint(l1[:-5]) # [1, 2, 3]\nNegative step\nl1 = [1, 2, 3, 4, 5, 6, 7, 8]\nprint(l1[5:1:-2]) # [6, 4]\nprint(l1[5::-1]) # [6, 5, 4, 3, 2, 1]\nprint(l1[:1:-1]) # [8, 7, 6, 5, 4, 3]\nprint(l1[1:5:-2]) # [] (already past end)\nSlice reversal\nl1 = [1, 2, 3, 4]\nprint(l1[::-1]) # [4, 3, 2, 1]\nSlicing creates new object \u2014 key exam trap\nl1 = [1, 2, 3, 4]\nl2 = l1\nl3 = l1[:]\nl1[-1] = 5\nprint(l1 == l2, l2 == l3) # True False (l3 is independent copy)\nChanging a list slice vs index\nl1 = [1, 2, 3, 4, 5, 6]\nl1[1:2] = [1, 1] # replaces element at index 1 with two elements\nprint(l1) # [1, 1, 1, 3, 4, 5, 6]\n\nl1 = [1, 2, 3, 4, 5, 6]\nl1[1] = [1, 1] # replaces element at index 1 with a list\nprint(l1) # [1, [1, 1], 3, 4, 5, 6]\nSlicing strings and tuples\nt1 = (1, 2, 3)\nprint(t1[1:]) # (2, 3)\ns1 = 'uva Amsterdam'\nprint(s1[5:-3:2]) # 'mtr'\nChanging string/tuple (must create new object)\ns1 = 'uva Amsterdam'\n# s1[6] = 's' # ERROR\ns1 = s1[:6] + 's' + s1[7:]\nprint(s1) # works\n\nt1 = (1, 4, 3)\n# t1[1] = 2 # ERROR\nt1 = t1[:1] + (2,) + t1[2:]\nprint(t1) # works" + }, + { + "item_id": "ks-0153de2f70", + "card_id": "w1-objects-and-names", + "topic": "Objects and Names", + "subtopic_id": "", + "subtopic_title": "", + "item_type": "source_lecture", + "bucket": "additional", + "selection_kind": "source", + "search_text": "Functions \u2014 basics\nFunctions are objects. Defined with def. Called with (). Built-in functions: print, id, len, type, del. Functions can return values. Methods are functions attached to objects.\nSimple function\ndef size(length, width):\n return length * width\nprint(size(2,3)) # 6" + }, + { + "item_id": "ks-df3b849d59", + "card_id": "w1-objects-and-names", + "topic": "Objects and Names", + "subtopic_id": "", + "subtopic_title": "", + "item_type": "source_lecture", + "bucket": "additional", + "selection_kind": "source", + "search_text": "Exam question types\nWhich code fragment will print the following output? / What will be printed by the following code fragment? / Which code fragment prints the SAME output as...? / One fragment prints different output from the others. / Which correctly solves the problem? Options may include: 'None of the above', 'Both', 'All', 'An error'." + }, + { + "item_id": "ks-419e787b39", + "card_id": "w1-objects-and-names", + "topic": "Objects and Names", + "subtopic_id": "", + "subtopic_title": "", + "item_type": "source_lecture", + "bucket": "additional", + "selection_kind": "source", + "search_text": "objects\n### Everything in Python is an object. Objects in Python have one id, one value, one type, and zero or more names\n
An assignment statement is one of the ways to create an object. An object created with an assignment statement will have a name, an id, a value and a type.\n
If you know the name you can ask for the id, the value, and the type" + }, + { + "item_id": "aiq-1", + "card_id": "w1-operators-and-truth", + "topic": "Operators and Truth", + "subtopic_id": "", + "subtopic_title": "", + "item_type": "ai_common_question", + "bucket": "aiQuestions", + "selection_kind": "direct", + "search_text": "What is the result of (a//b)*b + a%b?\nArithmetic operators" + }, + { + "item_id": "aiq-2", + "card_id": "w1-operators-and-truth", + "topic": "Operators and Truth", + "subtopic_id": "", + "subtopic_title": "", + "item_type": "ai_common_question", + "bucket": "aiQuestions", + "selection_kind": "direct", + "search_text": "Boolean operator precedence: not > and > or\na==1 or a==2 and b==1 or b==2 is evaluated as a==1 or (a==2 and b==1) or b==2" + }, + { + "item_id": "kp-1", + "card_id": "w1-operators-and-truth", + "topic": "Operators and Truth", + "subtopic_id": "w1-operators-and-truth-core", + "subtopic_title": "Arithmetic, Comparison, and Boolean Operators", + "item_type": "key_point", + "bucket": "keyPoints", + "selection_kind": "direct", + "search_text": "a+b, a-b, a*b: standard. a/b: always returns float. a//b: floor division (highest integer <= result). a%b: remainder. a**b: exponentiation. NOTE: ^ is NOT exponentiation in Python (it is XOR). (a//b)*b + a%b == a always." + }, + { + "item_id": "kp-1-d1", + "card_id": "w1-operators-and-truth", + "topic": "Operators and Truth", + "subtopic_id": "", + "subtopic_title": "", + "item_type": "key_point_detail", + "bucket": "keyPoints", + "selection_kind": "detail", + "search_text": "Floor division and modulo\nprint(5 // 3, 5 % 3) # 1 2\nprint(-5 // 3, -5 % 3) # -2 1\nprint(5 // 2, 5 % 2) # 2 1\nprint(-5 // 2, -5 % 2) # -3 1" + }, + { + "item_id": "kp-2", + "card_id": "w1-operators-and-truth", + "topic": "Operators and Truth", + "subtopic_id": "w1-operators-and-truth-core", + "subtopic_title": "Arithmetic, Comparison, and Boolean Operators", + "item_type": "key_point", + "bucket": "keyPoints", + "selection_kind": "direct", + "search_text": "==, !=, >, <, >=, <=. Always return True or False. Comparing floats can be tricky: 1.1+2.2 != 3.3 in Python due to floating-point precision. String/tuple/list comparison is element-by-element left to right; first differing element decides; if equal length and no differences, they are equal;" + }, + { + "item_id": "kp-2-d1", + "card_id": "w1-operators-and-truth", + "topic": "Operators and Truth", + "subtopic_id": "", + "subtopic_title": "", + "item_type": "key_point_detail", + "bucket": "keyPoints", + "selection_kind": "detail", + "search_text": "Float precision issue\nprint(1.1 + 2.2 == 3.3) # False" + }, + { + "item_id": "kp-2-d2", + "card_id": "w1-operators-and-truth", + "topic": "Operators and Truth", + "subtopic_id": "", + "subtopic_title": "", + "item_type": "key_point_detail", + "bucket": "keyPoints", + "selection_kind": "detail", + "search_text": "List/tuple comparison\nprint([1, 2, 3] < [1, 2, 3, 0]) # True (shorter is less)\nprint([2] < [1, 2, 3, 0]) # False (2 > 1 at index 0)" + }, + { + "item_id": "kp-3", + "card_id": "w1-operators-and-truth", + "topic": "Operators and Truth", + "subtopic_id": "w1-operators-and-truth-core", + "subtopic_title": "Arithmetic, Comparison, and Boolean Operators", + "item_type": "key_point", + "bucket": "keyPoints", + "selection_kind": "direct", + "search_text": "x and y: True only if both True. x or y: False only if both False. not x: inverts. NOTE: && and || are Python operators but do something different (bitwise). Precedence: 'not' first, then 'and', then 'or'. Use parentheses to avoid confusion." + }, + { + "item_id": "kp-3-d1", + "card_id": "w1-operators-and-truth", + "topic": "Operators and Truth", + "subtopic_id": "", + "subtopic_title": "", + "item_type": "key_point_detail", + "bucket": "keyPoints", + "selection_kind": "detail", + "search_text": "Precedence trap\na=1; b=3\nprint(a==1 or a==2 and b==1 or b==2) # True (WRONG: and binds tighter)\nprint((a==1 or a==2) and (b==1 or b==2)) # False (CORRECT)" + }, + { + "item_id": "ai-example-1", + "card_id": "w1-operators-and-truth", + "topic": "Operators and Truth", + "subtopic_id": "w1-operators-and-truth-core", + "subtopic_title": "Arithmetic, Comparison, and Boolean Operators", + "item_type": "ai_example", + "bucket": "aiExamples", + "selection_kind": "direct", + "search_text": "Floor division and modulo\nprint(5 // 3, 5 % 3) # 1 2\nprint(-5 // 3, -5 % 3) # -2 1\nprint(5 // 2, 5 % 2) # 2 1\nprint(-5 // 2, -5 % 2) # -3 1\na+b, a-b, a*b: standard. a/b: always returns float. a//b: floor division (highest integer <= result). a%b: remainder. a**b: exponentiation. NOTE: ^ is NOT exponentiation in Python (it is XOR). (a//b)*b + a%b == a always." + }, + { + "item_id": "ai-example-2", + "card_id": "w1-operators-and-truth", + "topic": "Operators and Truth", + "subtopic_id": "w1-operators-and-truth-core", + "subtopic_title": "Arithmetic, Comparison, and Boolean Operators", + "item_type": "ai_example", + "bucket": "aiExamples", + "selection_kind": "direct", + "search_text": "Float precision issue\nprint(1.1 + 2.2 == 3.3) # False\n==, !=, >, <, >=, <=. Always return True or False. Comparing floats can be tricky: 1.1+2.2 != 3.3 in Python due to floating-point precision. String/tuple/list comparison is element-by-element left to right; first differing element decides; if equal length and no differences, they are equal;" + }, + { + "item_id": "ai-example-3", + "card_id": "w1-operators-and-truth", + "topic": "Operators and Truth", + "subtopic_id": "w1-operators-and-truth-core", + "subtopic_title": "Arithmetic, Comparison, and Boolean Operators", + "item_type": "ai_example", + "bucket": "aiExamples", + "selection_kind": "direct", + "search_text": "List/tuple comparison\nprint([1, 2, 3] < [1, 2, 3, 0]) # True (shorter is less)\nprint([2] < [1, 2, 3, 0]) # False (2 > 1 at index 0)\n==, !=, >, <, >=, <=. Always return True or False. Comparing floats can be tricky: 1.1+2.2 != 3.3 in Python due to floating-point precision. String/tuple/list comparison is element-by-element left to right; first differing element decides; if equal length and no differences, they are equal;" + }, + { + "item_id": "ai-example-4", + "card_id": "w1-operators-and-truth", + "topic": "Operators and Truth", + "subtopic_id": "w1-operators-and-truth-core", + "subtopic_title": "Arithmetic, Comparison, and Boolean Operators", + "item_type": "ai_example", + "bucket": "aiExamples", + "selection_kind": "direct", + "search_text": "Precedence trap\na=1; b=3\nprint(a==1 or a==2 and b==1 or b==2) # True (WRONG: and binds tighter)\nprint((a==1 or a==2) and (b==1 or b==2)) # False (CORRECT)\nx and y: True only if both True. x or y: False only if both False. not x: inverts. NOTE: && and || are Python operators but do something different (bitwise). Precedence: 'not' first, then 'and', then 'or'. Use parentheses to avoid confusion." + }, + { + "item_id": "ai-example-5", + "card_id": "w1-operators-and-truth", + "topic": "Operators and Truth", + "subtopic_id": "w1-operators-and-truth-core", + "subtopic_title": "Arithmetic, Comparison, and Boolean Operators", + "item_type": "ai_example", + "bucket": "aiExamples", + "selection_kind": "direct", + "search_text": "arithmetic_operators\nprint(5//2, 5%2)\n2 1" + }, + { + "item_id": "ai-example-6", + "card_id": "w1-operators-and-truth", + "topic": "Operators and Truth", + "subtopic_id": "w1-operators-and-truth-core", + "subtopic_title": "Arithmetic, Comparison, and Boolean Operators", + "item_type": "ai_example", + "bucket": "aiExamples", + "selection_kind": "direct", + "search_text": "arithmetic_operators\nprint(4 + 3)\nprint(4 - 3)\nprint(4 * 3)\nprint(4 / 3)\nprint(4 / 2)\nprint(4 ** 3)\n7\n1\n12\n1.3333333333333333\n2.0\n64" + }, + { + "item_id": "ai-example-7", + "card_id": "w1-operators-and-truth", + "topic": "Operators and Truth", + "subtopic_id": "w1-operators-and-truth-core", + "subtopic_title": "Arithmetic, Comparison, and Boolean Operators", + "item_type": "ai_example", + "bucket": "aiExamples", + "selection_kind": "direct", + "search_text": "arithmetic_operators\nprint(5 // 3, 5 % 3)\nprint(-5 // 3, -5 % 3)\nprint(5 // 2, 5 % 2)\nprint(-5 // 2, -5 % 2)\n1 2\n-2 1\n2 1\n-3 1" + }, + { + "item_id": "ai-example-8", + "card_id": "w1-operators-and-truth", + "topic": "Operators and Truth", + "subtopic_id": "w1-operators-and-truth-core", + "subtopic_title": "Arithmetic, Comparison, and Boolean Operators", + "item_type": "ai_example", + "bucket": "aiExamples", + "selection_kind": "direct", + "search_text": "`==` versus `is`\n#\nimport random # The random module that can be used to generate pseudo-random numbers is part of the standard Python installation\n # but the name has still to be importent\na = random.randint(3, 9) # This generates an integer between 3 and 9 (both included), it is given the name 'a'\nb = random.randint(3, 9) # # This generates an integer between 3 and 9 (both included), it is given the name 'b'\nprint (a, b)\nprint(a==(a/b)*b + a%b) # == compares what is left of it to what is right of it and evaluates to True if both sides evaluate to the same value\n`==` compares value equality; `is` compares whether two names refer to the same object.\n8 4\nTrue" + }, + { + "item_id": "ks-03c874b8bb", + "card_id": "w1-operators-and-truth", + "topic": "Operators and Truth", + "subtopic_id": "", + "subtopic_title": "", + "item_type": "source_lecture", + "bucket": "recommended", + "selection_kind": "source", + "search_text": "Arithmetic operators\na+b, a-b, a*b: standard. a/b: always returns float. a//b: floor division (highest integer <= result). a%b: remainder. a**b: exponentiation. NOTE: ^ is NOT exponentiation in Python (it is XOR). (a//b)*b + a%b == a always.\nFloor division and modulo\nprint(5 // 3, 5 % 3) # 1 2\nprint(-5 // 3, -5 % 3) # -2 1\nprint(5 // 2, 5 % 2) # 2 1\nprint(-5 // 2, -5 % 2) # -3 1" + }, + { + "item_id": "ks-c0135e2a4a", + "card_id": "w1-operators-and-truth", + "topic": "Operators and Truth", + "subtopic_id": "", + "subtopic_title": "", + "item_type": "source_lecture", + "bucket": "recommended", + "selection_kind": "source", + "search_text": "Comparison operators\n==, !=, >, <, >=, <=. Always return True or False. Comparing floats can be tricky: 1.1+2.2 != 3.3 in Python due to floating-point precision. String/tuple/list comparison is element-by-element left to right; first differing element decides; if equal length and no differences, they are equal; shorter sequence is 'less than' longer if all elements match up to shorter length.\nFloat precision issue\nprint(1.1 + 2.2 == 3.3) # False\nList/tuple comparison\nprint([1, 2, 3] < [1, 2, 3, 0]) # True (shorter is less)\nprint([2] < [1, 2, 3, 0]) # False (2 > 1 at index 0)" + }, + { + "item_id": "ks-c815ffe1d5", + "card_id": "w1-operators-and-truth", + "topic": "Operators and Truth", + "subtopic_id": "", + "subtopic_title": "", + "item_type": "source_lecture", + "bucket": "recommended", + "selection_kind": "source", + "search_text": "Boolean operators\nx and y: True only if both True. x or y: False only if both False. not x: inverts. NOTE: && and || are Python operators but do something different (bitwise). Precedence: 'not' first, then 'and', then 'or'. Use parentheses to avoid confusion.\nPrecedence trap\na=1; b=3\nprint(a==1 or a==2 and b==1 or b==2) # True (WRONG: and binds tighter)\nprint((a==1 or a==2) and (b==1 or b==2)) # False (CORRECT)" + }, + { + "item_id": "cs-7eb8617d28", + "card_id": "w1-operators-and-truth", + "topic": "Operators and Truth", + "subtopic_id": "", + "subtopic_title": "", + "item_type": "source_notebook", + "bucket": "recommended", + "selection_kind": "source", + "search_text": "arithmetic_operators\nprint(5//2, 5%2)\n2 1" + }, + { + "item_id": "cs-3cb4b8e8f9", + "card_id": "w1-operators-and-truth", + "topic": "Operators and Truth", + "subtopic_id": "", + "subtopic_title": "", + "item_type": "source_notebook", + "bucket": "recommended", + "selection_kind": "source", + "search_text": "arithmetic_operators\nprint(4 + 3)\nprint(4 - 3)\nprint(4 * 3)\nprint(4 / 3)\nprint(4 / 2)\nprint(4 ** 3)\n7\n1\n12\n1.3333333333333333\n2.0\n64" + }, + { + "item_id": "cs-266616a010", + "card_id": "w1-operators-and-truth", + "topic": "Operators and Truth", + "subtopic_id": "", + "subtopic_title": "", + "item_type": "source_notebook", + "bucket": "recommended", + "selection_kind": "source", + "search_text": "arithmetic_operators\nprint(5 // 3, 5 % 3)\nprint(-5 // 3, -5 % 3)\nprint(5 // 2, 5 % 2)\nprint(-5 // 2, -5 % 2)\n1 2\n-2 1\n2 1\n-3 1" + }, + { + "item_id": "cs-4f8a5f420b", + "card_id": "w1-operators-and-truth", + "topic": "Operators and Truth", + "subtopic_id": "", + "subtopic_title": "", + "item_type": "source_notebook", + "bucket": "recommended", + "selection_kind": "source", + "search_text": "arithmetic_operators\n#\nimport random # The random module that can be used to generate pseudo-random numbers is part of the standard Python installation\n # but the name has still to be importent\na = random.randint(3, 9) # This generates an integer between 3 and 9 (both included), it is given the name 'a'\nb = random.randint(3, 9) # # This generates an integer between 3 and 9 (both included), it is given the name 'b'\nprint (a, b)\nprint(a==(a/b)*b + a%b) # == compares what is left of it to what is right of it and evaluates to True if both sides evaluate to the same value\n8 4\nTrue" + }, + { + "item_id": "aiq-1", + "card_id": "w1-sequences-and-access", + "topic": "Sequences and Access", + "subtopic_id": "", + "subtopic_title": "", + "item_type": "ai_common_question", + "bucket": "aiQuestions", + "selection_kind": "direct", + "search_text": "Slicing / mutability\nTrack which names point to the same object and which slice creates a copy before the mutation happens.\nSlicing / mutability" + }, + { + "item_id": "aiq-2", + "card_id": "w1-sequences-and-access", + "topic": "Sequences and Access", + "subtopic_id": "", + "subtopic_title": "", + "item_type": "ai_common_question", + "bucket": "aiQuestions", + "selection_kind": "direct", + "search_text": "Slicing negative step\nRead the slice as `start:stop:step`; with a negative step Python walks right-to-left and still excludes the stop position.\nSlicing negative step" + }, + { + "item_id": "aiq-3", + "card_id": "w1-sequences-and-access", + "topic": "Sequences and Access", + "subtopic_id": "", + "subtopic_title": "", + "item_type": "ai_common_question", + "bucket": "aiQuestions", + "selection_kind": "direct", + "search_text": "numbers = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]\na: starts at -1 (10), step -2: [10,8,6,4,2]. Correct. b: [::-2] starts at last (10), step -2: [10,8,6,4,2]. Correct. c: [::-1] reverses to [10,9,8,7,6,5,4,3,2,1], then [::2] takes every 2nd: [10,8,6,4,2]. Correct. d: [::2] gives [1,3,5,7,9], then [::-1] reverses: [9,7,5,3,1]. This does NOT give [10,8,6,4,2].\nExam \u2022 extra_practice \u2022 Q6" + }, + { + "item_id": "aiq-5", + "card_id": "w1-sequences-and-access", + "topic": "Sequences and Access", + "subtopic_id": "", + "subtopic_title": "", + "item_type": "ai_common_question", + "bucket": "aiQuestions", + "selection_kind": "direct", + "search_text": "str.upper() / string methods don't modify in place\ns.upper() returns a new string; s is unchanged. Must do s = s.upper()" + }, + { + "item_id": "aiq-6", + "card_id": "w1-sequences-and-access", + "topic": "Sequences and Access", + "subtopic_id": "", + "subtopic_title": "", + "item_type": "ai_common_question", + "bucket": "aiQuestions", + "selection_kind": "direct", + "search_text": "range() and slicing both exclusive at stop\nrange(1,10,3)\u2192[1,4,7] not including 10; l[2:7] goes up to but not including index 7" + }, + { + "item_id": "kp-1", + "card_id": "w1-sequences-and-access", + "topic": "Sequences and Access", + "subtopic_id": "w1-sequences-and-access-core", + "subtopic_title": "Indexing, Slicing, and range()", + "item_type": "key_point", + "bucket": "keyPoints", + "selection_kind": "direct", + "search_text": "Negative indices count from the end: `seq[-1]` is last and `seq[-len(seq)]` is first." + }, + { + "item_id": "kp-1-d1", + "card_id": "w1-sequences-and-access", + "topic": "Sequences and Access", + "subtopic_id": "", + "subtopic_title": "", + "item_type": "key_point_detail", + "bucket": "keyPoints", + "selection_kind": "detail", + "search_text": "Dense reference table\nPattern | Meaning | Example\nseq[i] | single element | x[-1]\nseq[a:b] | start inclusive, stop exclusive | x[1:4]\nseq[::-1] | reverse copy | x[::-1]\nseq[::2] | step through every other item | x[::2]" + }, + { + "item_id": "kp-2", + "card_id": "w1-sequences-and-access", + "topic": "Sequences and Access", + "subtopic_id": "w1-sequences-and-access-core", + "subtopic_title": "Indexing, Slicing, and range()", + "item_type": "key_point", + "bucket": "keyPoints", + "selection_kind": "direct", + "search_text": "`range(start, stop, step)` excludes `stop`; defaults are `start=0` and `step=1`, just like slicing excludes the stop index." + }, + { + "item_id": "kp-2-d1", + "card_id": "w1-sequences-and-access", + "topic": "Sequences and Access", + "subtopic_id": "", + "subtopic_title": "", + "item_type": "key_point_detail", + "bucket": "keyPoints", + "selection_kind": "detail", + "search_text": "range examples\nprint(list(range(6))) # [0, 1, 2, 3, 4, 5]\nprint(list(range(3,6))) # [3, 4, 5]\nprint(list(range(3,6,2))) # [3, 5]" + }, + { + "item_id": "kp-3", + "card_id": "w1-sequences-and-access", + "topic": "Sequences and Access", + "subtopic_id": "w1-sequences-and-access-core", + "subtopic_title": "Indexing, Slicing, and range()", + "item_type": "key_point", + "bucket": "keyPoints", + "selection_kind": "direct", + "search_text": "Pattern to remember: subset = numbers[::2][::-1]" + }, + { + "item_id": "ai-example-1", + "card_id": "w1-sequences-and-access", + "topic": "Sequences and Access", + "subtopic_id": "w1-sequences-and-access-core", + "subtopic_title": "Indexing, Slicing, and range()", + "item_type": "ai_example", + "bucket": "aiExamples", + "selection_kind": "direct", + "search_text": "range() output patterns\nprint(list(range(6))) # [0, 1, 2, 3, 4, 5]\nprint(list(range(3,6))) # [3, 4, 5]\nprint(list(range(3,6,2))) # [3, 5]\n`range(start, stop, step)` excludes `stop`; defaults are `start=0` and `step=1`, just like slicing excludes the stop index." + }, + { + "item_id": "ai-example-2", + "card_id": "w1-sequences-and-access", + "topic": "Sequences and Access", + "subtopic_id": "w1-sequences-and-access-core", + "subtopic_title": "Indexing, Slicing, and range()", + "item_type": "ai_example", + "bucket": "aiExamples", + "selection_kind": "direct", + "search_text": "print(\"This is a string\")\nprint(\"This is a string\")\nprint('This is another string')" + }, + { + "item_id": "ai-example-4", + "card_id": "w1-sequences-and-access", + "topic": "Sequences and Access", + "subtopic_id": "w1-sequences-and-access-core", + "subtopic_title": "Indexing, Slicing, and range()", + "item_type": "ai_example", + "bucket": "aiExamples", + "selection_kind": "direct", + "search_text": "String quotes and escaping\nprint(\"This gives no ' error\")\nprint('This gives no \" error')" + }, + { + "item_id": "ai-example-5", + "card_id": "w1-sequences-and-access", + "topic": "Sequences and Access", + "subtopic_id": "w1-sequences-and-access-core", + "subtopic_title": "Indexing, Slicing, and range()", + "item_type": "ai_example", + "bucket": "aiExamples", + "selection_kind": "direct", + "search_text": "a = 'This is a string'\na = 'This is a string' \nb = \"This is another string\"\nprint(a)\nprint(b)\nprint(a,b)" + }, + { + "item_id": "ai-example-6", + "card_id": "w1-sequences-and-access", + "topic": "Sequences and Access", + "subtopic_id": "w1-sequences-and-access-core", + "subtopic_title": "Indexing, Slicing, and range()", + "item_type": "ai_example", + "bucket": "aiExamples", + "selection_kind": "direct", + "search_text": "a = 'This is a string'; b = 6; c = 0.0\n#\na = 'This is a string'; b = 6; c = 0.0 \nprint(f\"We know {a =}, {b= }, and {c = }\")" + }, + { + "item_id": "ai-example-7", + "card_id": "w1-sequences-and-access", + "topic": "Sequences and Access", + "subtopic_id": "w1-sequences-and-access-core", + "subtopic_title": "Indexing, Slicing, and range()", + "item_type": "ai_example", + "bucket": "aiExamples", + "selection_kind": "direct", + "search_text": "slicing\nl1 = ['a', 'b']\nl2 = l1\nl2[-1] = 'c'\nprint(l1 == l3)\nl3 = l1[::]\nl3[-1] = 'c'\nprint(l1 == l3)" + }, + { + "item_id": "exam-intro_python_sample_final_24_25-18-w2-conditions", + "card_id": "w1-sequences-and-access", + "topic": "Sequences and Access", + "subtopic_id": "", + "subtopic_title": "", + "item_type": "source_exam", + "bucket": "recommended", + "selection_kind": "source", + "search_text": "How do you break a list into a list of lists, where each sublist contains 3 elements?\nA\nB\nC\nD\nA\nOption A uses range(0, 7, 3) which generates 0, 3, 6. The slices x[0:3], x[3:6], and x[6:9] correctly partition the list." + }, + { + "item_id": "exam-extra_practice-6-w1-sequences-and-access", + "card_id": "w1-sequences-and-access", + "topic": "Sequences and Access", + "subtopic_id": "", + "subtopic_title": "", + "item_type": "source_exam", + "bucket": "recommended", + "selection_kind": "source", + "search_text": "numbers = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]\n\nWhich of the following lines of code will NOT create a list with the name subset, and the value [10, 8, 6, 4, 2]?\na\nb\nc\nd\nd\na: starts at -1 (10), step -2: [10,8,6,4,2]. Correct. b: [::-2] starts at last (10), step -2: [10,8,6,4,2]. Correct. c: [::-1] reverses to [10,9,8,7,6,5,4,3,2,1], then [::2] takes every 2nd: [10,8,6,4,2]. Correct. d: [::2] gives [1,3,5,7,9], then [::-1] reverses: [9,7,5,3,1]. This does NOT give [10,8,6,4,2]. Correct answer (the one that does NOT work): d." + }, + { + "item_id": "ks-685cd3d828", + "card_id": "w1-sequences-and-access", + "topic": "Sequences and Access", + "subtopic_id": "", + "subtopic_title": "", + "item_type": "source_lecture", + "bucket": "recommended", + "selection_kind": "source", + "search_text": "Indexing\nForward: 0, 1, 2, ... len-1. Backward: -1 (last), -2 (second to last), ..., -len (first). l1[0] == l1[-len(l1)]" + }, + { + "item_id": "ks-be78ccac04", + "card_id": "w1-sequences-and-access", + "topic": "Sequences and Access", + "subtopic_id": "", + "subtopic_title": "", + "item_type": "source_lecture", + "bucket": "recommended", + "selection_kind": "source", + "search_text": "range()\nrange(start, stop, step). start default=0, step default=1. Stop is NOT inclusive. Works like slicing but defaults differ slightly.\nrange examples\nprint(list(range(6))) # [0, 1, 2, 3, 4, 5]\nprint(list(range(3,6))) # [3, 4, 5]\nprint(list(range(3,6,2))) # [3, 5]" + }, + { + "item_id": "manual-import-names", + "card_id": "w1-functions-and-imports", + "topic": "Functions and Imports", + "subtopic_id": "", + "subtopic_title": "", + "item_type": "ai_common_question", + "bucket": "aiQuestions", + "selection_kind": "direct", + "search_text": "How do different import forms change the names you can use locally?\n`import math` gives `math.sqrt`, `import math as m` gives `m.sqrt`, and `from math import sqrt` gives `sqrt(...)` directly.\nimport math\nimport math as m\nfrom math import sqrt" + }, + { + "item_id": "manual-print-vs-return", + "card_id": "w1-functions-and-imports", + "topic": "Functions and Imports", + "subtopic_id": "", + "subtopic_title": "", + "item_type": "ai_common_question", + "bucket": "aiQuestions", + "selection_kind": "direct", + "search_text": "What is the difference between printing a value and returning a value from a function?\n`print(x)` shows a value on screen. `return x` sends a value back to the caller so it can be stored, reused, or printed later.\ndef f(x):\n return x + 1\n\nprint(f(3))" + }, + { + "item_id": "manual-implicit-none", + "card_id": "w1-functions-and-imports", + "topic": "Functions and Imports", + "subtopic_id": "", + "subtopic_title": "", + "item_type": "ai_common_question", + "bucket": "aiQuestions", + "selection_kind": "direct", + "search_text": "What does a function return if it reaches the end without `return`?\nPython returns `None` if no `return` statement is executed.\ndef f():\n print('hi')\n\nprint(f())" + }, + { + "item_id": "kp-1", + "card_id": "w1-functions-and-imports", + "topic": "Functions and Imports", + "subtopic_id": "w1-functions-and-imports-core", + "subtopic_title": "Built-ins Intro, Functions, and Modules", + "item_type": "key_point", + "bucket": "keyPoints", + "selection_kind": "direct", + "search_text": "`import x` keeps the module name, `import x as y` renames it, and `from x import z` brings `z` into scope directly." + }, + { + "item_id": "kp-1-d1", + "card_id": "w1-functions-and-imports", + "topic": "Functions and Imports", + "subtopic_id": "", + "subtopic_title": "", + "item_type": "key_point_detail", + "bucket": "keyPoints", + "selection_kind": "detail", + "search_text": "Import styles\nimport numpy\nnumpy.random.randint(1, 10) # works\n\nimport numpy as np\nnp.random.randint(1, 10) # works\nnumpy.random.randint(1, 10) # ERROR\n\nfrom numpy.random import randint\nrandint(1, 10) # works\n\nfrom numpy.random import randint as rnd\nrnd(1, 10) # works\nrandint(1, 10) # ERROR" + }, + { + "item_id": "kp-1-d2", + "card_id": "w1-functions-and-imports", + "topic": "Functions and Imports", + "subtopic_id": "", + "subtopic_title": "", + "item_type": "key_point_detail", + "bucket": "keyPoints", + "selection_kind": "detail", + "search_text": "Dense reference table\nCall | Use | Typical result\nint('123') | string to integer | 123\nfloat('123') | string to float | 123.0\nstr(123.0) | number to string | '123.0'\nround(x, 2) | round for display/checking | 2 decimals" + }, + { + "item_id": "kp-2", + "card_id": "w1-functions-and-imports", + "topic": "Functions and Imports", + "subtopic_id": "w1-functions-and-imports-core", + "subtopic_title": "Built-ins Intro, Functions, and Modules", + "item_type": "key_point", + "bucket": "keyPoints", + "selection_kind": "direct", + "search_text": "Use `print(...)` to display a value. A function groups reusable code and may also return a value to its caller." + }, + { + "item_id": "ai-example-1", + "card_id": "w1-functions-and-imports", + "topic": "Functions and Imports", + "subtopic_id": "w1-functions-and-imports-core", + "subtopic_title": "Built-ins Intro, Functions, and Modules", + "item_type": "ai_example", + "bucket": "aiExamples", + "selection_kind": "direct", + "search_text": "Import module under its original name\nimport numpy\nnumpy.random.randint(1, 10) # works\n\nimport numpy as np\nnp.random.randint(1, 10) # works\nnumpy.random.randint(1, 10) # ERROR\n\nfrom numpy.random import randint\nrandint(1, 10) # works\n\nfrom numpy.random import randint as rnd\nrnd(1, 10) # works\nrandint(1, 10) # ERROR\n`import x` keeps the module name, `import x as y` renames it, and `from x import z` brings `z` into scope directly." + }, + { + "item_id": "ai-example-2", + "card_id": "w1-functions-and-imports", + "topic": "Functions and Imports", + "subtopic_id": "w1-functions-and-imports-core", + "subtopic_title": "Built-ins Intro, Functions, and Modules", + "item_type": "ai_example", + "bucket": "aiExamples", + "selection_kind": "direct", + "search_text": "Direct import plus alias binds both names\nclear_names()\n\nimport extension as ex\ntry:\n print(ex.YEAR)\nexcept Exception as e:\n print(e)\n\ntry:\n print(extension.YEAR)\nexcept Exception as e:\n print(e)\nKeep track of which name is actually available after `import`, `from ... import ...`, or `as`.\n2025\nname 'extension' is not defined" + }, + { + "item_id": "ai-example-3", + "card_id": "w1-functions-and-imports", + "topic": "Functions and Imports", + "subtopic_id": "w1-functions-and-imports-core", + "subtopic_title": "Built-ins Intro, Functions, and Modules", + "item_type": "ai_example", + "bucket": "aiExamples", + "selection_kind": "direct", + "search_text": "from-import binds only the imported name\nclear_names()\n\nimport extension\nimport extension as ex\ntry:\n print(ex.YEAR)\nexcept Exception as e:\n print(e)\n\ntry:\n print(extension.YEAR)\nexcept Exception as e:\n print(e)\nKeep track of which name is actually available after `import`, `from ... import ...`, or `as`.\n2025\n2025" + }, + { + "item_id": "ai-example-4", + "card_id": "w1-functions-and-imports", + "topic": "Functions and Imports", + "subtopic_id": "w1-functions-and-imports-core", + "subtopic_title": "Built-ins Intro, Functions, and Modules", + "item_type": "ai_example", + "bucket": "aiExamples", + "selection_kind": "direct", + "search_text": "Aliased from-import uses the alias locally\nclear_names()\n\nfrom extension import create_absolute_year\ntry:\n print(create_absolute_year(1))\nexcept Exception as e:\n print(e)\n\ntry:\n print(YEAR)\nexcept Exception as e:\n print(e)\nKeep track of which name is actually available after `import`, `from ... import ...`, or `as`.\n2026\nname 'YEAR' is not defined" + }, + { + "item_id": "ai-example-5", + "card_id": "w1-functions-and-imports", + "topic": "Functions and Imports", + "subtopic_id": "w1-functions-and-imports-core", + "subtopic_title": "Built-ins Intro, Functions, and Modules", + "item_type": "ai_example", + "bucket": "aiExamples", + "selection_kind": "direct", + "search_text": "import module does not create bare globals\nclear_names()\n\nfrom extension import create_absolute_year as cay\ntry:\n print(create_absolute_year(1))\nexcept Exception as e:\n print(e)\n\ntry:\n print(cay(1))\nexcept Exception as e:\n print(e)\nKeep track of which name is actually available after `import`, `from ... import ...`, or `as`.\nname 'create_absolute_year' is not defined\n2026" + }, + { + "item_id": "ai-example-6", + "card_id": "w1-functions-and-imports", + "topic": "Functions and Imports", + "subtopic_id": "w1-functions-and-imports-core", + "subtopic_title": "Built-ins Intro, Functions, and Modules", + "item_type": "ai_example", + "bucket": "aiExamples", + "selection_kind": "direct", + "search_text": "Import module under its original name\nclear_names()\ntry:\n print(YEAR)\nexcept Exception as e:\n print(Exception)\n\ntry:\n print(extension.YEAR)\nexcept Exception as e:\n print(e)\n\nimport extension\ntry:\n print(YEAR)\nexcept Exception as e:\n print(e)\n\ntry:\n print(extension.YEAR)\nexcept Exception as e:\n print(e)\nKeep track of which name is actually available after `import`, `from ... import ...`, or `as`.\n\nname 'extension' is not defined\nname 'YEAR' is not defined\n2025" + }, + { + "item_id": "ai-example-8", + "card_id": "w1-functions-and-imports", + "topic": "Functions and Imports", + "subtopic_id": "w1-functions-and-imports-core", + "subtopic_title": "Built-ins Intro, Functions, and Modules", + "item_type": "ai_example", + "bucket": "aiExamples", + "selection_kind": "direct", + "search_text": "Income tax branches and return shape\nSuppose your country imposes the following tax brackets:\nBracket Tax Taxable income\nrate Over Not over\n1 10% $0 $11,000\n2 12% $11,000 $45,000\n3 22% $45,000 $95,000\n4 32% $95,000\nIf your gross income is $50,000, you will pay 10% tax on the first $11,000, 12% tax on the next $34,000 and 22% tax on the last $5,000.\nWhich of the following function will return the output containing your net_income and your total_tax given your gross_income?\nFor example:\nIf we call the function as:\nincome_tax_calculator(50000)\nit should return:\n{'total_tax': 6280.0, 'net_income': 43720.0}\nA def income_tax_calculator(gross_income):\nresults = {}\nrate_1 = 0.10\nrate_2 = 0.12\nrate_3 = 0.22\nrate_4 = 0.32\nbracket_1 = 11000\nbracket_2 = 45000 - 11000\nbracket_3 = 95000 - 45000\nif gross_income > 95000:\ntotal_tax = ((gross_income - 95000) * rate_4) + (bracket_3 * rate_3) + (bracket_2 * rate_2)\n+ (bracket_1 * rate_1)\nelif 95000 >= gross_income > 45000:\ntotal_tax = ((gross_income - 45000) * rate_3) + (bracket_2 * rate_2) + (bracket_1 * rate_1)\nelif 45000 >= gross_income > 11000:\ntotal_tax = ((gross_income - 11000) * rate_2) + (bracket_1 * rate_1)\nelse:\ntotal_tax = gross_income * rate_1\nnet_income = gross_income - total_tax\nresults['total_tax'] = round(total_tax, 2)\nresults['net_income'] = round(net_income, 2)\nreturn results\nB def income_tax_calculator(gross_income):\n\u200b results = {}\nrate_1 = 0.10\nrate_2 = 0.12\nrate_3 = 0.22\nrate_4 = 0.32\nbracket_1 = 11000\nbracket_2 = 45000 - 11001\nbracket_3 = 95000 - 45001\ntotal_tax = (gross_income - 95001) * rate_4 + (bracket_3 * rate_3) + (bracket_2 * rate_2) +\n(bracket_1 * rate_1)\nnet_income = lambda gross_income, total_tax: gross_income - total_tax\nresults['total_tax'] = round(total_tax, 2)\nresults['net_income'] = round(net_income, 2)\nreturn results\nC def income_tax_calculator(gross_income):\n\u200b results = {}\nrate_1 = 0.10\nrate_2 = 0.12\nrate_3 = 0.22\nrate_4 = 0.32\nif gross_income <= 11000:\ntotal_tax = gross_income * rate_1\nif 45000 > gross_income > 11000:\ntotal_tax += (45000 - gross_income) * rate_2\nif 95000 > gross_income > 45000:\ntotal_tax += (95000 - gross_income) * rate_3\nelse:\ntotal_tax += (gross_income - 95000) * rate_4\nnet_income = gross_income - total_tax\nresults['total_tax'] = total_tax\nresults['net_income'] = net_income\nreturn(total_tax, net_income)\nD All of three functions will work as intended.\nCheck branch boundaries, rounding, and whether the function returns `{'total_tax': ..., 'net_income': ...}`." + }, + { + "item_id": "exam-intro_python_sample_final_24_25-24-w2-conditions", + "card_id": "w1-functions-and-imports", + "topic": "Functions and Imports", + "subtopic_id": "", + "subtopic_title": "", + "item_type": "source_exam", + "bucket": "recommended", + "selection_kind": "source", + "search_text": "Which script does NOT print the correct answer for the area of a circle?\nA\nB\nC\nD\nC\nIf math is imported as constants, it must be referred to as 'constants.pi'. 'math.pi' will no longer be available unless 'math' was also imported directly." + }, + { + "item_id": "exam-Resit 22/23-5-w1-functions-and-imports", + "card_id": "w1-functions-and-imports", + "topic": "Functions and Imports", + "subtopic_id": "", + "subtopic_title": "", + "item_type": "source_exam", + "bucket": "recommended", + "selection_kind": "source", + "search_text": "Suppose you have a list called x. Which of the following code segments will print the following list?\n[5, 4, 3, 2, 1]\na\nb\nc\nd\nc\nOption A extracts unique elements with `set(x)`, resulting in `{1, 2, 3, 4, 5}`, then sorts them in reverse order, giving `[5, 4, 3, 2, 1]`. Option B uses list slicing `x[::-2]` which steps backwards through `x` by 2, retrieving indices -1, -3, -5, -7, and -9, which correspond to 5, 4, 3, 2, 1. Thus, both A and B are correct." + }, + { + "item_id": "exam-midterm_2023-12-w1-functions-and-imports", + "card_id": "w1-functions-and-imports", + "topic": "Functions and Imports", + "subtopic_id": "", + "subtopic_title": "", + "item_type": "source_exam", + "bucket": "recommended", + "selection_kind": "source", + "search_text": "You want to write a program to calculate your income tax for 2023." + }, + { + "item_id": "exam-midterm_2024-15-w1-functions-and-imports", + "card_id": "w1-functions-and-imports", + "topic": "Functions and Imports", + "subtopic_id": "", + "subtopic_title": "", + "item_type": "source_exam", + "bucket": "recommended", + "selection_kind": "source", + "search_text": "Consider the following code snippet:\ndef main(lst, condition=lambda x: x):\ny = []\nfor x in lst:\nif condition(x):\ny.append(x)\nreturn y\nWhat will this function return, when called in the following way:\nmain([1, 2, 3, 4, 5, 6, 7, 8, 9, 10], lambda x: x % 2 != 0)\nA [1, 3, 5, 7, 9]\nB [2, 4, 6, 8, 10]\nC [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]\nD None" + }, + { + "item_id": "exam-midterm_2024-16-w1-functions-and-imports", + "card_id": "w1-functions-and-imports", + "topic": "Functions and Imports", + "subtopic_id": "", + "subtopic_title": "", + "item_type": "source_exam", + "bucket": "recommended", + "selection_kind": "source", + "search_text": "You need to write a function called weather_alert that accepts a string argument, which is a color code of the weather alert system." + }, + { + "item_id": "ks-f43422a4cf", + "card_id": "w1-functions-and-imports", + "topic": "Functions and Imports", + "subtopic_id": "", + "subtopic_title": "", + "item_type": "source_lecture", + "bucket": "recommended", + "selection_kind": "source", + "search_text": "Importing packages\nMultiple import styles. 'import X' makes X available. 'import X as Y' renames. 'from X import Z' brings Z directly into namespace. 'from X import Z as W' renames. Once you use 'as', the original name is no longer accessible.\nImport styles\nimport numpy\nnumpy.random.randint(1, 10) # works\n\nimport numpy as np\nnp.random.randint(1, 10) # works\nnumpy.random.randint(1, 10) # ERROR\n\nfrom numpy.random import randint\nrandint(1, 10) # works\n\nfrom numpy.random import randint as rnd\nrnd(1, 10) # works\nrandint(1, 10) # ERROR" + }, + { + "item_id": "ks-b6a39f66a2", + "card_id": "w1-functions-and-imports", + "topic": "Functions and Imports", + "subtopic_id": "", + "subtopic_title": "", + "item_type": "source_lecture", + "bucket": "recommended", + "selection_kind": "source", + "search_text": "intro\n### Print is a function and tells Python to output the argument (that what is between the brackets after the function name) on your screen\n
  • A function is a grouping of code that can perform a certain task and can be re-used \n
  • Print is a built-in function, that is a function that is part of the standard implementation of Python. Built-in fuctions like any function, can be used by calling their name. Built-in functions are already copied to your computer and the names of some of them like print, don't need to be imported\n
  • User functions are functions defined by you or other people that are not part of the standard Python implementation. (You will learn how to write your own\u2026" + }, + { + "item_id": "cs-beb6591b24", + "card_id": "w1-functions-and-imports", + "topic": "Functions and Imports", + "subtopic_id": "", + "subtopic_title": "", + "item_type": "source_notebook", + "bucket": "recommended", + "selection_kind": "source", + "search_text": "imports\nclear_names()\n\nimport extension as ex\ntry:\n print(ex.YEAR)\nexcept Exception as e:\n print(e)\n\ntry:\n print(extension.YEAR)\nexcept Exception as e:\n print(e)\n2025\nname 'extension' is not defined" + }, + { + "item_id": "cs-6d0d650063", + "card_id": "w1-functions-and-imports", + "topic": "Functions and Imports", + "subtopic_id": "", + "subtopic_title": "", + "item_type": "source_notebook", + "bucket": "recommended", + "selection_kind": "source", + "search_text": "imports\nclear_names()\n\nimport extension\nimport extension as ex\ntry:\n print(ex.YEAR)\nexcept Exception as e:\n print(e)\n\ntry:\n print(extension.YEAR)\nexcept Exception as e:\n print(e)\n2025\n2025" + }, + { + "item_id": "cs-4155022ebf", + "card_id": "w1-functions-and-imports", + "topic": "Functions and Imports", + "subtopic_id": "", + "subtopic_title": "", + "item_type": "source_notebook", + "bucket": "additional", + "selection_kind": "source", + "search_text": "imports\nclear_names()\n\nfrom extension import create_absolute_year\ntry:\n print(create_absolute_year(1))\nexcept Exception as e:\n print(e)\n\ntry:\n print(YEAR)\nexcept Exception as e:\n print(e)\n2026\nname 'YEAR' is not defined" + }, + { + "item_id": "cs-23b2cfd4d6", + "card_id": "w1-functions-and-imports", + "topic": "Functions and Imports", + "subtopic_id": "", + "subtopic_title": "", + "item_type": "source_notebook", + "bucket": "additional", + "selection_kind": "source", + "search_text": "imports\nclear_names()\n\nfrom extension import create_absolute_year as cay\ntry:\n print(create_absolute_year(1))\nexcept Exception as e:\n print(e)\n\ntry:\n print(cay(1))\nexcept Exception as e:\n print(e)\nname 'create_absolute_year' is not defined\n2026" + }, + { + "item_id": "cs-5b89a10dcd", + "card_id": "w1-functions-and-imports", + "topic": "Functions and Imports", + "subtopic_id": "", + "subtopic_title": "", + "item_type": "source_notebook", + "bucket": "additional", + "selection_kind": "source", + "search_text": "imports\nclear_names()\ntry:\n print(YEAR)\nexcept Exception as e:\n print(Exception)\n\ntry:\n print(extension.YEAR)\nexcept Exception as e:\n print(e)\n\nimport extension\ntry:\n print(YEAR)\nexcept Exception as e:\n print(e)\n\ntry:\n print(extension.YEAR)\nexcept Exception as e:\n print(e)\n\nname 'extension' is not defined\nname 'YEAR' is not defined\n2025" + }, + { + "item_id": "cs-c25503e5db", + "card_id": "w1-functions-and-imports", + "topic": "Functions and Imports", + "subtopic_id": "", + "subtopic_title": "", + "item_type": "source_notebook", + "bucket": "additional", + "selection_kind": "source", + "search_text": "imports\n%%writefile extension.py\n# In this cell we create a python file and write that to the hard disk (either of your computer or to the cloud depending where you run your code.\n# We will import this file to show how to import the names of objects \n# into your Python program\nYEAR = 2025\ndef create_absolute_year(x):\n return YEAR + x\nOverwriting extension.py" + }, + { + "item_id": "aiq-1", + "card_id": "w2-dictionaries-and-mappings", + "topic": "Dictionaries and Mappings", + "subtopic_id": "", + "subtopic_title": "", + "item_type": "ai_common_question", + "bucket": "aiQuestions", + "selection_kind": "direct", + "search_text": "Suppose you have a dictionary called characters, of which keys are strings and values are lists of strings.\nCheck whether the method mutates the list in place and what the list looks like after each call.\nExam \u2022 trial_midterm \u2022 Q2" + }, + { + "item_id": "aiq-2", + "card_id": "w2-dictionaries-and-mappings", + "topic": "Dictionaries and Mappings", + "subtopic_id": "", + "subtopic_title": "", + "item_type": "ai_common_question", + "bucket": "aiQuestions", + "selection_kind": "direct", + "search_text": "Which update makes `library['books'] = 6` and adds `library['years']`?\nCheck whether membership is testing keys, and trace any lookup or mutation on the dictionary.\nExam \u2022 trial_midterm \u2022 Q8" + }, + { + "item_id": "aiq-3", + "card_id": "w2-dictionaries-and-mappings", + "topic": "Dictionaries and Mappings", + "subtopic_id": "", + "subtopic_title": "", + "item_type": "ai_common_question", + "bucket": "aiQuestions", + "selection_kind": "direct", + "search_text": "What does `list(x.values()) + list(x.keys())` print?\nCheck whether membership is testing keys, and trace any lookup or mutation on the dictionary.\nExam \u2022 trial_midterm \u2022 Q10\nSuppose you have the following dictionary:\nx = {1: 10, 2: 20, 3: 30, 4: 40}\nWhat will the following line of code print?\nprint(list(x.values()) + list(x.keys()))\nA This code will result in an error because you cannot concatenate two lists using the + operator.\nB [10, 20, 30, 40, 1, 2, 3, 4]\nC [11, 22, 33, 44]\nD [(1, 10), (2, 20), (3, 30), (4, 40)]" + }, + { + "item_id": "aiq-6", + "card_id": "w2-dictionaries-and-mappings", + "topic": "Dictionaries and Mappings", + "subtopic_id": "", + "subtopic_title": "", + "item_type": "ai_common_question", + "bucket": "aiQuestions", + "selection_kind": "direct", + "search_text": "RuntimeError: dictionary changed size during iteration\nAdding or deleting dict entries while iterating over it causes RuntimeError" + }, + { + "item_id": "kp-1", + "card_id": "w2-dictionaries-and-mappings", + "topic": "Dictionaries and Mappings", + "subtopic_id": "w2-dictionaries-and-mappings-core", + "subtopic_title": "Creation, Lookup, Updates, and Key Constraints", + "item_type": "key_point", + "bucket": "keyPoints", + "selection_kind": "direct", + "search_text": "Dicts map unique immutable keys to values. `key in d` checks keys, and equality ignores insertion order." + }, + { + "item_id": "kp-1-d1", + "card_id": "w2-dictionaries-and-mappings", + "topic": "Dictionaries and Mappings", + "subtopic_id": "", + "subtopic_title": "", + "item_type": "key_point_detail", + "bucket": "keyPoints", + "selection_kind": "detail", + "search_text": "Creating and using dicts\ncapitals = {}\ncapitals = dict()\ncapitals = {'Andorra': 'Andorra la Vella', 'Belgium': 'Brussels'}\nprint(capitals['Belgium']) # Brussels\ndel(capitals['Belgium']) # delete key\ncapitals['Netherlands'] = 'Amsterdam' # insert/update\ncapitals.update({'France': 'Paris'}) # insert/update multiple" + }, + { + "item_id": "kp-1-d2", + "card_id": "w2-dictionaries-and-mappings", + "topic": "Dictionaries and Mappings", + "subtopic_id": "", + "subtopic_title": "", + "item_type": "key_point_detail", + "bucket": "keyPoints", + "selection_kind": "detail", + "search_text": "Dict membership checks KEYS, not values\nd = {1: 4, 2: 3}\nprint(1 in d) # True (1 is a key)\nprint(4 in d) # False (4 is a value, not a key)" + }, + { + "item_id": "kp-1-d3", + "card_id": "w2-dictionaries-and-mappings", + "topic": "Dictionaries and Mappings", + "subtopic_id": "", + "subtopic_title": "", + "item_type": "key_point_detail", + "bucket": "keyPoints", + "selection_kind": "detail", + "search_text": "Dense reference table\nOperation | What it gives | Exam note\nd[key] | value lookup | Key must exist\nkey in d | membership on keys | not values\nd.items() | (key, value) pairs | good for loops\nd.update(...) | mutates dict | returns None" + }, + { + "item_id": "kp-2", + "card_id": "w2-dictionaries-and-mappings", + "topic": "Dictionaries and Mappings", + "subtopic_id": "w2-dictionaries-and-mappings-core", + "subtopic_title": "Creation, Lookup, Updates, and Key Constraints", + "item_type": "key_point", + "bucket": "keyPoints", + "selection_kind": "direct", + "search_text": "Use `.keys()`, `.values()`, and `.items()` for dictionary views; looping over a dict directly gives keys." + }, + { + "item_id": "kp-2-d1", + "card_id": "w2-dictionaries-and-mappings", + "topic": "Dictionaries and Mappings", + "subtopic_id": "", + "subtopic_title": "", + "item_type": "key_point_detail", + "bucket": "keyPoints", + "selection_kind": "detail", + "search_text": "Looping over dict\ncapitals = {'Andorra': 'Andorra la Vella', 'Belgium': 'Brussels'}\nfor key in capitals.keys():\n print(key)\nfor val in capitals.values():\n print(val)\nfor key, value in capitals.items():\n print(key, value)\n# These two are equivalent:\nfor key in capitals:\nfor key in capitals.keys():" + }, + { + "item_id": "ai-example-1", + "card_id": "w2-dictionaries-and-mappings", + "topic": "Dictionaries and Mappings", + "subtopic_id": "w2-dictionaries-and-mappings-core", + "subtopic_title": "Creation, Lookup, Updates, and Key Constraints", + "item_type": "ai_example", + "bucket": "aiExamples", + "selection_kind": "direct", + "search_text": "Creating and using dicts\ncapitals = {}\ncapitals = dict()\ncapitals = {'Andorra': 'Andorra la Vella', 'Belgium': 'Brussels'}\nprint(capitals['Belgium']) # Brussels\ndel(capitals['Belgium']) # delete key\ncapitals['Netherlands'] = 'Amsterdam' # insert/update\ncapitals.update({'France': 'Paris'}) # insert/update multiple\nDicts map unique immutable keys to values. `key in d` checks keys, and equality ignores insertion order." + }, + { + "item_id": "ai-example-2", + "card_id": "w2-dictionaries-and-mappings", + "topic": "Dictionaries and Mappings", + "subtopic_id": "w2-dictionaries-and-mappings-core", + "subtopic_title": "Creation, Lookup, Updates, and Key Constraints", + "item_type": "ai_example", + "bucket": "aiExamples", + "selection_kind": "direct", + "search_text": "Dict membership checks KEYS, not values\nd = {1: 4, 2: 3}\nprint(1 in d) # True (1 is a key)\nprint(4 in d) # False (4 is a value, not a key)\nDicts map unique immutable keys to values. `key in d` checks keys, and equality ignores insertion order." + }, + { + "item_id": "ai-example-4", + "card_id": "w2-dictionaries-and-mappings", + "topic": "Dictionaries and Mappings", + "subtopic_id": "w2-dictionaries-and-mappings-core", + "subtopic_title": "Creation, Lookup, Updates, and Key Constraints", + "item_type": "ai_example", + "bucket": "aiExamples", + "selection_kind": "direct", + "search_text": "Dictionary creation and lookup\nsquares = {1:1, 2:4, 3:9, 4:16}\nprint(squares)\nl1 = [1, 2, 3, 4]\nl2 = [1, 4, 9, 16]\nsquares = dict(zip(l1, l2))\nprint(squares)\nCheck whether the code is looking up a key, iterating with `.items()`, or mutating the dictionary." + }, + { + "item_id": "ai-example-5", + "card_id": "w2-dictionaries-and-mappings", + "topic": "Dictionaries and Mappings", + "subtopic_id": "w2-dictionaries-and-mappings-core", + "subtopic_title": "Creation, Lookup, Updates, and Key Constraints", + "item_type": "ai_example", + "bucket": "aiExamples", + "selection_kind": "direct", + "search_text": "Dictionary creation and lookup\nsquares = {}\nprint(squares)\nsquares = dict()\nprint(squares)\nCheck whether the code is looking up a key, iterating with `.items()`, or mutating the dictionary." + }, + { + "item_id": "ai-example-6", + "card_id": "w2-dictionaries-and-mappings", + "topic": "Dictionaries and Mappings", + "subtopic_id": "w2-dictionaries-and-mappings-core", + "subtopic_title": "Creation, Lookup, Updates, and Key Constraints", + "item_type": "ai_example", + "bucket": "aiExamples", + "selection_kind": "direct", + "search_text": "Dictionary creation and lookup\nsquares = {1:1, 2:4, 3:9, 4:16}\ndel(squares[2])\nprint(squares)\nCheck whether the code is looking up a key, iterating with `.items()`, or mutating the dictionary." + }, + { + "item_id": "ai-example-7", + "card_id": "w2-dictionaries-and-mappings", + "topic": "Dictionaries and Mappings", + "subtopic_id": "w2-dictionaries-and-mappings-core", + "subtopic_title": "Creation, Lookup, Updates, and Key Constraints", + "item_type": "ai_example", + "bucket": "aiExamples", + "selection_kind": "direct", + "search_text": "Dictionary creation and lookup\na = 1\nb = {1:1}\nprint({a:b})\ntry:\n print({b:a})\nexcept Exception as e:\n print(e)\nCheck whether the code is looking up a key, iterating with `.items()`, or mutating the dictionary." + }, + { + "item_id": "ai-example-8", + "card_id": "w2-dictionaries-and-mappings", + "topic": "Dictionaries and Mappings", + "subtopic_id": "w2-dictionaries-and-mappings-core", + "subtopic_title": "Creation, Lookup, Updates, and Key Constraints", + "item_type": "ai_example", + "bucket": "aiExamples", + "selection_kind": "direct", + "search_text": "Dictionary creation and lookup\ncapitals = {'Estonia': 'Tallinn', 'Belgium': 'Brussels', 'France': 'Paris'}\nprint(capitals['Belgium'])\nCheck whether the code is looking up a key, iterating with `.items()`, or mutating the dictionary." + }, + { + "item_id": "exam-intro_python_sample_final_24_25-19-w3-defining-and-calling-functions", + "card_id": "w2-dictionaries-and-mappings", + "topic": "Dictionaries and Mappings", + "subtopic_id": "", + "subtopic_title": "", + "item_type": "source_exam", + "bucket": "recommended", + "selection_kind": "source", + "search_text": "Which of the following programs correctly returns a dictionary where values are sums of input values whose keys are <= the output key?\nA\nB\nC\nD\nC\nBoth methods correctly calculate the cumulative sums based on key values, though Option B is more efficient." + }, + { + "item_id": "exam-intro_python_sample_final_24_25-20-w3-defining-and-calling-functions", + "card_id": "w2-dictionaries-and-mappings", + "topic": "Dictionaries and Mappings", + "subtopic_id": "", + "subtopic_title": "", + "item_type": "source_exam", + "bucket": "recommended", + "selection_kind": "source", + "search_text": "What is the result of the program comparing d1 (from zip) and d2 (from enumerate)?\nA\nB\nC\nD\nA\nBoth d1 and d2 result in the same dictionary: {1: 2, 2: 3, 3: 4, 4: 5}." + }, + { + "item_id": "exam-intro_python_sample_final_24_25-21-w3-defining-and-calling-functions", + "card_id": "w2-dictionaries-and-mappings", + "topic": "Dictionaries and Mappings", + "subtopic_id": "", + "subtopic_title": "", + "item_type": "source_exam", + "bucket": "recommended", + "selection_kind": "source", + "search_text": "The following codes all print the same value, except one. Which one?\nA\nB\nC\nD\nA\nIterating directly over a dictionary (for key, value in d1) only yields keys. This will cause a ValueError when trying to unpack into two variables." + }, + { + "item_id": "exam-trial-final-exam-py22-4-w2-dictionaries-and-mappings", + "card_id": "w2-dictionaries-and-mappings", + "topic": "Dictionaries and Mappings", + "subtopic_id": "", + "subtopic_title": "", + "item_type": "source_exam", + "bucket": "recommended", + "selection_kind": "source", + "search_text": "You have to create a dictionary called roman_nums where the keys are the integers from 1 to 5 (both are inclusive) and the values are their corresponding Roman numeral symbols.\n\nThat is, if we execute the following command:\nprint(roman_nums)\nthe output should be:\n{1: 'I', 2: 'II', 3: 'III', 4: 'IV', 5: 'V'}\n\nWhich of the following code segments works as intended?\na\nb\nc\nd\na\nOption A correctly zips the numbers 1 to 5 with the corresponding Roman numerals to create the dictionary." + }, + { + "item_id": "exam-trial-final-exam-py22-5-w2-dictionaries-and-mappings", + "card_id": "w2-dictionaries-and-mappings", + "topic": "Dictionaries and Mappings", + "subtopic_id": "", + "subtopic_title": "", + "item_type": "source_exam", + "bucket": "recommended", + "selection_kind": "source", + "search_text": "You have two lists representing the names and ages of individuals:\nnames = ['Alice', 'Bob', 'Charlie', 'David']\nages = [25, 30, 35, 40]\n\nYou need to create a dictionary called person_dict where the keys are the names and the values are the ages.\nHowever, you want to include only the names that start with the letter 'A' or with the letter 'C'.\n\nSo executing the following command:\nprint(person_dict)\nshould give the following output:\n{'Alice': 25, 'Charlie': 35}\n\nWhich of the following code segments works as intended?\na\nb\nc\nd\na\nOption A correctly iterates through both lists simultaneously using zip and assigns the correct keys and values." + }, + { + "item_id": "exam-trial-final-exam-py22-6-w2-dictionaries-and-mappings", + "card_id": "w2-dictionaries-and-mappings", + "topic": "Dictionaries and Mappings", + "subtopic_id": "", + "subtopic_title": "", + "item_type": "source_exam", + "bucket": "recommended", + "selection_kind": "source", + "search_text": "You have the following dictionary that represents the performance ratings of employees in a company:\nemployee_ratings = {'John': 8, 'Sarah': 9, 'Michael': 7, 'Emma': 9, 'David': 6}\n\nYou need to find and print the name of the employee(s) with the highest performance rating.\n\nWhich of the following code segments works as intended?\na\nb\nc\nd\na\nOption A correctly identifies the maximum rating from the values and then prints the corresponding employees." + }, + { + "item_id": "exam-Resit 22/23-7-w2-dictionaries-and-mappings", + "card_id": "w2-dictionaries-and-mappings", + "topic": "Dictionaries and Mappings", + "subtopic_id": "", + "subtopic_title": "", + "item_type": "source_exam", + "bucket": "recommended", + "selection_kind": "source", + "search_text": "Assume you already have a list of strings called words.\nYou need to create a dictionary called word_lengths, where the keys are the strings in the list words and the values are their lengths.\nWhich of the following code segments will work as intended?\na\nb\nc\nd\na\nOption A is a valid dictionary comprehension that iterates through `words`, setting each `word` as the key and `len(word)` as the value." + }, + { + "item_id": "exam-Trial final - Introduction to Python - 22/23-4-w2-dictionaries-and-mappings", + "card_id": "w2-dictionaries-and-mappings", + "topic": "Dictionaries and Mappings", + "subtopic_id": "", + "subtopic_title": "", + "item_type": "source_exam", + "bucket": "recommended", + "selection_kind": "source", + "search_text": "You have to create a dictionary called vowels_ASCII where the keys are the lowercase vowels (a, e, i, o, u) and the values are their corresponding ASCII values.\nThe ASCII (American Standard Code for Information Interchange) is a character encoding standard that assigns unique numerical values to characters.\n\nThat is, if we execute the following command:\nprint(vowels_ASCII)\n\nthe output should be:\n{'a': 97, 'e': 101, 'i': 105, 'o': 111, 'u': 117}\n\nWhich of the following code segments work(s) as intended?\n\nHint: the ord() function returns a unique numerical value to a character. The function takes a unit-length text as an argument and returns the assigned unique numerical value.\n\nFor example:\nord('a')\n\nreturns:\n97\na\nb\nc\nd\nc\nOption A iterates over 'aeiou' and correctly creates the dictionary. Option B iterates over 'aeiou' and also checks if the vowel is in 'aeiou', which is redundant but still valid and produces the correct dictionary. Thus, both work correctly." + }, + { + "item_id": "exam-Trial final - Introduction to Python - 22/23-5-w2-dictionaries-and-mappings", + "card_id": "w2-dictionaries-and-mappings", + "topic": "Dictionaries and Mappings", + "subtopic_id": "", + "subtopic_title": "", + "item_type": "source_exam", + "bucket": "recommended", + "selection_kind": "source", + "search_text": "Suppose you have three variables called player1_goals, player2_goals, and player3_goals. Each of the variables contains a list of integers that represents the number of goals scored by the football players in five different matches:\n\nplayer1_goals = [2, 1, 3, 2, 1]\nplayer2_goals = [0, 1, 1, 3, 2]\nplayer3_goals = [1, 0, 2, 1, 3]\n\nYou want to create a new dictionary called match_goals where the keys are the match numbers (starting from 1) and the values are a tuple containing the total goals scored by each player in that match.\n\nSo, if we execute the following command:\nprint(match_goals)\n\nthe output should be:\n{1: (2, 0, 1), 2: (1, 1, 0), 3: (3, 1, 2), 4: (2, 3, 1), 5: (1, 2, 3)}\n\nWhich of the following code segments works as intended?\na\nb\nc\nd\na\nOption A uses zip to combine the lists and enumerate with start=1 to get match numbers starting from 1. It assigns a tuple of goals to each match number. Option B assigns the sum instead of a tuple. Options C and D don't use start=1 for enumerate, so keys will start from 0." + }, + { + "item_id": "exam-Trial final - Introduction to Python - 22/23-6-w2-dictionaries-and-mappings", + "card_id": "w2-dictionaries-and-mappings", + "topic": "Dictionaries and Mappings", + "subtopic_id": "", + "subtopic_title": "", + "item_type": "source_exam", + "bucket": "recommended", + "selection_kind": "source", + "search_text": "You have the following dictionary that represents the monthly sales of a store:\nmonthly_sales = {'January': 1500, 'February': 2200, 'March': 1800, 'April': 2400, 'May': 2000, 'June': 2800}\n\nYou need to calculate the average sales for the first three months (January, February, and March). Which of the following code segments works as intended?\na\nb\nc\nd\na\nDictionaries are not sliceable, so options B and D will raise TypeErrors. Option C creates a list of tuples, and the sum() function cannot add tuples together in this context (it will raise a TypeError when trying to add an int to a tuple). Option A extracts the first three keys, gets their corresponding values in a list comprehension, and calculates the average correctly." + }, + { + "item_id": "exam-trial_midterm-2-w2-dictionaries-and-mappings", + "card_id": "w2-dictionaries-and-mappings", + "topic": "Dictionaries and Mappings", + "subtopic_id": "", + "subtopic_title": "", + "item_type": "source_exam", + "bucket": "recommended", + "selection_kind": "source", + "search_text": "Suppose you have a dictionary called characters, of which keys are strings and values are lists of strings." + }, + { + "item_id": "exam-trial_midterm-8-w2-dictionaries-and-mappings", + "card_id": "w2-dictionaries-and-mappings", + "topic": "Dictionaries and Mappings", + "subtopic_id": "", + "subtopic_title": "", + "item_type": "source_exam", + "bucket": "recommended", + "selection_kind": "source", + "search_text": "Suppose you have the following dictionary:\nlibrary = {\"books\": 5,\n\"genres\": ['action', 'romance', 'thriller', 'classics']}\nYou want to:\n- add a key \"years\", of which the value is a list of strings that are the years of publication, i.e., [\"1932\" , \"2012\", \"1899\",\n\"2000\", \"1984\"],\n- change the value of the key \"books\" to 6.\nThe new value of the dictionary library should be:\n{\"books\" : 6,\n\"genres\" : ['action', 'romance', 'thriller', 'classics'],\n\"years\" : [\"1932\" , \"2012\", \"1899\", \"2000\", \"1984\"]}\nWhich of the programs below will work as intended?\nA library[\"books\"] = 6\nlibrary.update({\"years\": [\"1932\" , \"2012\", \"1899\", \"2000\", \"1984\"]})\nB library[\"books\"] = 6\nlibrary[\"years\"] = [\"1932\" , \"2012\", \"1899\", \"2000\", \"1984\"]\nC Both of the given options\nD None of the given options" + }, + { + "item_id": "exam-trial_midterm-10-w2-dictionaries-and-mappings", + "card_id": "w2-dictionaries-and-mappings", + "topic": "Dictionaries and Mappings", + "subtopic_id": "", + "subtopic_title": "", + "item_type": "source_exam", + "bucket": "recommended", + "selection_kind": "source", + "search_text": "Suppose you have the following dictionary:\nx = {1: 10, 2: 20, 3: 30, 4: 40}\nWhat will the following line of code print?\nprint(list(x.values()) + list(x.keys()))\nA This code will result in an error because you cannot concatenate two lists using the + operator.\nB [10, 20, 30, 40, 1, 2, 3, 4]\nC [11, 22, 33, 44]\nD [(1, 10), (2, 20), (3, 30), (4, 40)]" + }, + { + "item_id": "exam-trial_midterm-19-w2-dictionaries-and-mappings", + "card_id": "w2-dictionaries-and-mappings", + "topic": "Dictionaries and Mappings", + "subtopic_id": "", + "subtopic_title": "", + "item_type": "source_exam", + "bucket": "recommended", + "selection_kind": "source", + "search_text": "Suppose you have the following function:\ndef my_count_function(string):\ncounts = {}\nfor letter in string:\nif letter in counts:\ncounts[letter] += 1\nelse:\ncounts[letter] = 1\nreturn counts\nAnd you create the following two dictionaries:\napple_count = my_count_function(\"apple\")\npeach_count = my_count_function(\"peach\")\nWhich of the code snippets of code below prints something different than the other code snippets?\nA print(len(apple_count.keys()))\nB print(len(peach_count.keys()))\nC print(sum(apple_count.values()))\nD print(sum(peach_count.values()))" + }, + { + "item_id": "ks-65c4de2e9d", + "card_id": "w2-dictionaries-and-mappings", + "topic": "Dictionaries and Mappings", + "subtopic_id": "", + "subtopic_title": "", + "item_type": "source_lecture", + "bucket": "recommended", + "selection_kind": "source", + "search_text": "Dictionaries\nSets of key:value pairs. Keys must be unique and immutable (hashable). Dictionaries are unordered for equality ({1:1,2:2}=={2:2,1:1} is True). Cannot be sorted. You can check membership with 'in' \u2014 this checks KEYS only. Keys() gives key sequence, values() gives value sequence, items() gives tuples.\nCreating and using dicts\ncapitals = {}\ncapitals = dict()\ncapitals = {'Andorra': 'Andorra la Vella', 'Belgium': 'Brussels'}\nprint(capitals['Belgium']) # Brussels\ndel(capitals['Belgium']) # delete key\ncapitals['Netherlands'] = 'Amsterdam' # insert/update\ncapitals.update({'France': 'Paris'}) # insert/update multiple\nDict membership checks KEYS, not values\nd = {1: 4, 2: 3}\nprint(1 in d) # True (1 is a key)\nprint(4 in d) # False (4 is a value, not a key)\nCreating dict from two lists\nl1 = [1, 2, 3, 4]\nl2 = [1, 4, 9, 16]\nsquares = dict(zip(l1, l2))\nprint(squares) # {1:1, 2:4, 3:9, 4:16}\nDict equality ignores order\nprint({1:1, 2:2} == {2:2, 1:1}) # True\nprint([1,2] == [2,1]) # False" + }, + { + "item_id": "ks-adb6d9f967", + "card_id": "w2-dictionaries-and-mappings", + "topic": "Dictionaries and Mappings", + "subtopic_id": "", + "subtopic_title": "", + "item_type": "source_lecture", + "bucket": "recommended", + "selection_kind": "source", + "search_text": "Looping over dictionaries\n.keys() \u2192 key sequence. .values() \u2192 value sequence. .items() \u2192 sequence of (key, value) tuples. 'for key in dict' is the same as 'for key in dict.keys()'.\nLooping over dict\ncapitals = {'Andorra': 'Andorra la Vella', 'Belgium': 'Brussels'}\nfor key in capitals.keys():\n print(key)\nfor val in capitals.values():\n print(val)\nfor key, value in capitals.items():\n print(key, value)\n# These two are equivalent:\nfor key in capitals:\nfor key in capitals.keys():" + }, + { + "item_id": "exam-trial_midterm-23-w2-dictionaries-and-mappings", + "card_id": "w2-dictionaries-and-mappings", + "topic": "Dictionaries and Mappings", + "subtopic_id": "", + "subtopic_title": "", + "item_type": "source_exam", + "bucket": "additional", + "selection_kind": "source", + "search_text": "You have to write a function called summarize which take a list of integers as an argument." + }, + { + "item_id": "exam-midterm_2023-5-w2-dictionaries-and-mappings", + "card_id": "w2-dictionaries-and-mappings", + "topic": "Dictionaries and Mappings", + "subtopic_id": "", + "subtopic_title": "", + "item_type": "source_exam", + "bucket": "additional", + "selection_kind": "source", + "search_text": "What is the output of the program below?" + }, + { + "item_id": "exam-midterm_2023-6-w2-dictionaries-and-mappings", + "card_id": "w2-dictionaries-and-mappings", + "topic": "Dictionaries and Mappings", + "subtopic_id": "", + "subtopic_title": "", + "item_type": "source_exam", + "bucket": "additional", + "selection_kind": "source", + "search_text": "Suppose you have the following dictionary:\nsample_dict = {\n\"name\": \"Kim\",\n\"age\": 25,\n\"birthdate\": \"3-2-1998\",\n\"city\": \"Amsterdam\"}\nSuppose you want to create a dictionary that only contains the keys 'name' and 'city'.\nWhich of the following code snippets return(s) the desired dictionary?\nA keys = [\"name\", \"city\"]\nnew_dict = {}\nfor k in keys:\nnew_dict[k] = sample_dict[k]\nnew_dict\nB keys = [\"age\", \"birthdate\"]\nnew_dict = {}\nnew_keys = sample_dict.keys() - keys\nfor k in new_keys:\nnew_dict[k] = sample_dict[k]\nnew_dict\nC None of the given options\nD Both of the given options" + }, + { + "item_id": "exam-midterm_2023-7-w2-dictionaries-and-mappings", + "card_id": "w2-dictionaries-and-mappings", + "topic": "Dictionaries and Mappings", + "subtopic_id": "", + "subtopic_title": "", + "item_type": "source_exam", + "bucket": "additional", + "selection_kind": "source", + "search_text": "Suppose you have the following dictionary:\ncloset = {\n\"shirts\" : 5,\n\"colors\" : ['red', 'yellow', 'blue', 'pink']\n}\nYou want to:\n- add a key \"shoes\" which has a value that is a list containing the strings \"sneakers\" and \"heels\"\n- add 2 shirts, so that the value of the key \"shirts\" becomes 7\nSo the final dictionary should look like:\n{'shirts': 7, 'colors': ['red', 'yellow', 'blue', 'pink'], 'shoes': ['sneakers', 'heels']}\nWhich of the programs below will work as intended?\nA shoes = {'shoes': ['sneakers', 'heels']}\ncloset[\"shirts\"] = 7\ncloset = dict(zip(closet, shoes))\nB closet.keys() = closet.keys() + \"shoes\"\ncloset.values() = [7, ['red', 'yellow', 'blue', 'pink'], ['sneakers', 'heels']]\nC Both of the given options\nD None of the given options" + }, + { + "item_id": "exam-midterm_2023-8-w2-dictionaries-and-mappings", + "card_id": "w2-dictionaries-and-mappings", + "topic": "Dictionaries and Mappings", + "subtopic_id": "", + "subtopic_title": "", + "item_type": "source_exam", + "bucket": "additional", + "selection_kind": "source", + "search_text": "Suppose you have the following function:\ndef my_count_function(string):\ncounts = {}\nfor letter in string:\ncounts[letter] = string.count(letter)\nreturn counts\nAnd you create the following two dictionaries:\ndesk_count = my_count_function(\"desk\")\nlaptop_count = my_count_function(\"laptop\")\nWhich of the lines of code below returns something different than the rest?\nA len(desk_count)\nB max(laptop_count.values())*2\nC sum(desk_count.values())\nD sum(laptop_count.keys())" + }, + { + "item_id": "exam-midterm_2024-7-w2-dictionaries-and-mappings", + "card_id": "w2-dictionaries-and-mappings", + "topic": "Dictionaries and Mappings", + "subtopic_id": "", + "subtopic_title": "", + "item_type": "source_exam", + "bucket": "additional", + "selection_kind": "source", + "search_text": "Suppose you have the following a dictionary called students, which contains three sub-dictionaries:\nstudents = {\"james\": {\"name\": \"James\",\n\"homework\": [90.0, 97.0, 75.0, 92.0],\n\"quizzes\": [88.0, 40.0, 94.0],\n\"tests\": [75.0, 90.0]},\n\"eva\": {\"name\": \"Eva\",\n\"homework\": [100.0, 92.0, 98.0, 100.0],\n\"quizzes\": [82.0, 83.0, 91.0],\n\"tests\": [89.0, 97.0]},\n\"david\": {\"name\": \"David\",\n\"homework\": [0.0, 87.0, 75.0, 22.0],\n\"quizzes\": [0.0, 75.0, 78.0],\n\"tests\": [100.0, 100.0]}\n}\nYou want to create a function that calculates the average final course grade of a student.\nThe final course grade is calculated as 20% average homework grade, 10% average quizzes grade and 70% average tests grade.\nWhich of the following programs will work as intended and will give the final course grade of Eva?\nA def average(numbers):\nreturn sum(numbers)/(len(numbers))\ndef final_average(student):\nhomework = average(student['homework'])\nquizzes = average(student['quizzes'])\ntests = average(student['tests'])\nreturn round(0.2*homework + 0.1*quizzes + 0.7*tests, 2)\nfinal_average(students[\"eva\"])\nB def final_average(student):\ndef average(numbers):\nreturn sum(numbers)/(len(numbers)\nhomework = average(student['home\u2026" + }, + { + "item_id": "exam-midterm_2024-8-w2-dictionaries-and-mappings", + "card_id": "w2-dictionaries-and-mappings", + "topic": "Dictionaries and Mappings", + "subtopic_id": "", + "subtopic_title": "", + "item_type": "source_exam", + "bucket": "additional", + "selection_kind": "source", + "search_text": "You need to write a function called dict_keys that checks whether a certain key is in available in a certain dictionary." + }, + { + "item_id": "exam-midterm_2024-10-w2-dictionaries-and-mappings", + "card_id": "w2-dictionaries-and-mappings", + "topic": "Dictionaries and Mappings", + "subtopic_id": "", + "subtopic_title": "", + "item_type": "source_exam", + "bucket": "additional", + "selection_kind": "source", + "search_text": "Suppose you have the following dictionary:\nlibrary = {\"books\": 5,\n\"genres\": ['action', 'romance', 'thriller', 'classics']}\nYou want to:\n- add a key \"years\", of which the value is a list of strings that are the years of publication, i.e., [\"1932\" , \"2012\", \"1899\", \"2000\", \"1984\"],\n- change the value of the key \"books\" to 6.\nThe new value of the dictionary library should be:\n{\"books\" : 6,\n\"genres\" : ['action', 'romance', 'thriller', 'classics'],\n\"years\" : [\"1932\" , \"2012\", \"1899\", \"2000\", \"1984\"]}\nWhich of the programs below will work as intended?\nA library[\"books\"] = 6\nlibrary.update({\"years\": [\"1932\" , \"2012\", \"1899\", \"2000\", \"1984\"]})\nB library[\"books\"] = 6\nlibrary[\"years\"] = [\"1932\" , \"2012\", \"1899\", \"2000\", \"1984\"]\nC Both of the given options\nD None of the given options" + }, + { + "item_id": "exam-midterm_2024-11-w2-dictionaries-and-mappings", + "card_id": "w2-dictionaries-and-mappings", + "topic": "Dictionaries and Mappings", + "subtopic_id": "", + "subtopic_title": "", + "item_type": "source_exam", + "bucket": "additional", + "selection_kind": "source", + "search_text": "Suppose you have the following function:\ndef my_count_function(string):\ncounts = {}\nfor letter in string:\nif letter in counts:\ncounts[letter] += 1\nelse:\ncounts[letter] = 1\nreturn counts\nAnd you create the following two dictionaries:\napple_count = my_count_function(\"apple\")\npeach_count = my_count_function(\"peach\")\nWhich of the code snippets of code below prints something different than the other code snippets?\nA print(sum(apple_count.values()))\nB print(len(apple_count.keys()))\nC print(sum(peach_count.values()))\nD print(len(peach_count.keys()))" + }, + { + "item_id": "exam-midterm_2024-12-w2-dictionaries-and-mappings", + "card_id": "w2-dictionaries-and-mappings", + "topic": "Dictionaries and Mappings", + "subtopic_id": "", + "subtopic_title": "", + "item_type": "source_exam", + "bucket": "additional", + "selection_kind": "source", + "search_text": "Suppose you have the following dictionary:\nx = {1: 10, 2: 20, 3: 30, 4: 40}\nWhat will the following line of code print?\nprint(list(x.values()) + list(x.keys()))\nA [10, 20, 30, 40, 1, 2, 3, 4]\nB [11, 22, 33, 44]\nC This code will result in an error because you cannot concatenate two lists using the + operator.\nD [(1, 10), (2, 20), (3, 30), (4, 40)]" + }, + { + "item_id": "exam-extra_practice-3-w2-dictionaries-and-mappings", + "card_id": "w2-dictionaries-and-mappings", + "topic": "Dictionaries and Mappings", + "subtopic_id": "", + "subtopic_title": "", + "item_type": "source_exam", + "bucket": "additional", + "selection_kind": "source", + "search_text": "Adelbrecht and Hortensia competed in a game. You have a dictionary with two subdictionaries:\n\nresults = {'Adelbrecht':{'attempt1':3,'attempt2':2,'attempt3':6},'Hortensia':{'attempt1':1,'attempt2':6}}\n\nYou would like to create a dictionary in which the keys are the highest and lowest scores and the values are a list of names of the players that attained the corresponding scores.\n\nWhich of the following code snippets implements this?\na\nb\nc\nd\nc\nBoth snippets correctly find the global max (6) and min (1), then iterate to find which players achieved those scores. Both produce the same correct output. Note: both Adelbrecht and Hortensia achieved score 6, so winners = ['Adelbrecht', 'Hortensia']." + }, + { + "item_id": "exam-extra_practice-4-w2-dictionaries-and-mappings", + "card_id": "w2-dictionaries-and-mappings", + "topic": "Dictionaries and Mappings", + "subtopic_id": "", + "subtopic_title": "", + "item_type": "source_exam", + "bucket": "additional", + "selection_kind": "source", + "search_text": "math_scores = {'John': 85, 'Sarah': 92, 'Michael': 78, 'Emma': 90, 'David': 82}\n\nYou want to find and print the names of the students who scored above the average score.\n\nWhich of the following code segments will work as intended?\na\nb\nc\nd\nb\nOption a has an indentation error (the for loop is indented under the average_score line as if it's a block, but there's no colon). This causes an IndentationError. Option b works correctly. Actually option a depends on whether the indentation shown is a tab after a plain statement \u2014 in Python that's an IndentationError. So only b works. Correct: b." + }, + { + "item_id": "exam-extra_practice-5-w2-dictionaries-and-mappings", + "card_id": "w2-dictionaries-and-mappings", + "topic": "Dictionaries and Mappings", + "subtopic_id": "", + "subtopic_title": "", + "item_type": "source_exam", + "bucket": "additional", + "selection_kind": "source", + "search_text": "students = ['A','B','C','D','E','F']\ngrades = [9,10,9,11,10,9]\n\nYou need to create a dictionary called grade_counts that counts the number of students in each grade level.\n\nExpected: {9:3, 10:2, 11:1}\n\nWhich of the following code segments will work as intended?\na\nb\nc\nd\na\nOption a correctly counts grades: initialises to 0 and increments. Produces {9:3, 10:2, 11:1}. Option b creates lists of student names, not counts \u2014 produces {9:['A','C','F'], 10:['B','E'], 11:['D']}, not the required format. Correct: a." + }, + { + "item_id": "exam-extra_practice-8-w2-dictionaries-and-mappings", + "card_id": "w2-dictionaries-and-mappings", + "topic": "Dictionaries and Mappings", + "subtopic_id": "", + "subtopic_title": "", + "item_type": "source_exam", + "bucket": "additional", + "selection_kind": "source", + "search_text": "x = {'a': [1, 2], 'b':[3, 4], 'c':[5, 6], 'd':[7, 8]}\n\nWhich of the following lines of code will print True?\na\nb\nc\nd\nd\na: x['a'][1]=2, x['b'][0]=3, 2*3=6, x['c'][1]=6. True. b: x['b'][0]=3, x['c'][0]=5, 3+5=8, x['d'][1]=8. True. c: x['d'][0]=7, x['c'][0]=5, 7-5=2, x['a'][1]=2. True. All are True, so d is correct." + }, + { + "item_id": "exam-extra_practice-12-w2-dictionaries-and-mappings", + "card_id": "w2-dictionaries-and-mappings", + "topic": "Dictionaries and Mappings", + "subtopic_id": "", + "subtopic_title": "", + "item_type": "source_exam", + "bucket": "additional", + "selection_kind": "source", + "search_text": "def counter(y):\n\tx = {}\n\tfor index, element in enumerate(y):\n\t\tif index != int(element) and int(element) % 2 == 0:\n\t\t\tx[element] = len(element)\n\treturn x\n\nWhat will this function return when called as:\ncounter(['12345678', '1', '123', '1234', '12345', '12', '6', '1', '123456'])\na\nb\nc\nd\na\nindex 0: '12345678', int=12345678, index(0)!=12345678 \u2713, even \u2713 \u2192 add, len=8. index 1: '1', int=1, index==int \u2192 skip. index 2: '123', int=123, odd \u2192 skip. index 3: '1234', int=1234, index(3)!=1234 \u2713, even \u2713 \u2192 add, len=4. index 4: '12345', int=12345, odd \u2192 skip. index 5: '12', int=12, index(5)!=12 \u2713, even \u2713 \u2192 add, len=2. index 6: '6', int=6, index(6)==6 \u2192 skip. index 7: '1', int=1, odd \u2192 skip. index 8: '123456', int=123456, index(8)!=123456 \u2713, even \u2713 \u2192 add, len=6. Result: {'12345678':8,'1234':4,'12':2,'123456':6}. Correct: a." + }, + { + "item_id": "aiq-1", + "card_id": "w2-lists-and-sets", + "topic": "Lists and Sets", + "subtopic_id": "", + "subtopic_title": "", + "item_type": "ai_common_question", + "bucket": "aiQuestions", + "selection_kind": "direct", + "search_text": "Assume you already have a variable a, which is an integer between 1 and 4.\nExam \u2022 midterm_2023 \u2022 Q15\nmylist = [1, 3, 5, 7, 9]\nprint(mylist[a] + mylist[-a])" + }, + { + "item_id": "aiq-2", + "card_id": "w2-lists-and-sets", + "topic": "Lists and Sets", + "subtopic_id": "", + "subtopic_title": "", + "item_type": "ai_common_question", + "bucket": "aiQuestions", + "selection_kind": "direct", + "search_text": "List method effects and resulting list\nCheck whether the method mutates the list in place and what the list looks like after each call.\nExam \u2022 midterm_2023 \u2022 Q16\nConsider the following code snippet:\nmylist = [1, 3, 2, 3, 4, 5, 3, 3]\nmylist.append('3')\nmylist.remove(3)\nprint(mylist.count(3))\nWhat will be the output?\nHint: The remove() list method removes the first occurrence of the element with the specified value." + }, + { + "item_id": "aiq-3", + "card_id": "w2-lists-and-sets", + "topic": "Lists and Sets", + "subtopic_id": "", + "subtopic_title": "", + "item_type": "ai_common_question", + "bucket": "aiQuestions", + "selection_kind": "direct", + "search_text": "list\nExam \u2022 midterm_2024 \u2022 Q22\nConsider the following code snippet:\nx = [\"a\", \"b\", \"c\", \"4\"]\nprint(x[-3] + x[3]*3)\nWhich of the following code snippet will print the same output?" + }, + { + "item_id": "aiq-4", + "card_id": "w2-lists-and-sets", + "topic": "Lists and Sets", + "subtopic_id": "", + "subtopic_title": "", + "item_type": "ai_common_question", + "bucket": "aiQuestions", + "selection_kind": "direct", + "search_text": "Unordered collections equality\n{1:1,2:2}=={2:2,1:1} is True; {1,2}=={2,1} is True; [1,2]==[2,1] is False" + }, + { + "item_id": "kp-1", + "card_id": "w2-lists-and-sets", + "topic": "Lists and Sets", + "subtopic_id": "w2-lists-and-sets-core", + "subtopic_title": "Sequences, Uniqueness, and Common Operations", + "item_type": "key_point", + "bucket": "keyPoints", + "selection_kind": "direct", + "search_text": "Lists, tuples, strings are SEQUENCES (ordered). Dicts and sets are NOT sequences (unordered for equality). All are called collections." + }, + { + "item_id": "kp-1-d1", + "card_id": "w2-lists-and-sets", + "topic": "Lists and Sets", + "subtopic_id": "", + "subtopic_title": "", + "item_type": "key_point_detail", + "bucket": "keyPoints", + "selection_kind": "detail", + "search_text": "Ordering comparison\nprint([1,2] == [2,1]) # False (ordered)\nprint((1,2) == (2,1)) # False (ordered)\nprint('12' == '21') # False (ordered)\nprint({1,2} == {2,1}) # True (unordered)\nprint({1:1,2:2}=={2:2,1:1}) # True (unordered)" + }, + { + "item_id": "kp-2", + "card_id": "w2-lists-and-sets", + "topic": "Lists and Sets", + "subtopic_id": "w2-lists-and-sets-core", + "subtopic_title": "Sequences, Uniqueness, and Common Operations", + "item_type": "key_point", + "bucket": "keyPoints", + "selection_kind": "direct", + "search_text": "Unordered collection of unique values. Empty set MUST be set() \u2014 {} creates empty dict. Elements must be immutable. No indexing. Methods: .add(), .remove(), .update()." + }, + { + "item_id": "kp-2-d1", + "card_id": "w2-lists-and-sets", + "topic": "Lists and Sets", + "subtopic_id": "", + "subtopic_title": "", + "item_type": "key_point_detail", + "bucket": "keyPoints", + "selection_kind": "detail", + "search_text": "Set operations\ncountries = set() # empty set (NOT {})\ncountries = {'Andorra', 'Belgium'}\nprint({1,2,2} == {2,1}) # True (duplicates ignored)\nprint(len({1,2,2})) # 2\ncountries.remove('Andorra')\ncountries.add('Greece')\ncountries.update({'Spain', 'Italy'})" + }, + { + "item_id": "ai-example-1", + "card_id": "w2-lists-and-sets", + "topic": "Lists and Sets", + "subtopic_id": "w2-lists-and-sets-core", + "subtopic_title": "Sequences, Uniqueness, and Common Operations", + "item_type": "ai_example", + "bucket": "aiExamples", + "selection_kind": "direct", + "search_text": "Ordering comparison\nprint([1,2] == [2,1]) # False (ordered)\nprint((1,2) == (2,1)) # False (ordered)\nprint('12' == '21') # False (ordered)\nprint({1,2} == {2,1}) # True (unordered)\nprint({1:1,2:2}=={2:2,1:1}) # True (unordered)\nLists, tuples, strings are SEQUENCES (ordered). Dicts and sets are NOT sequences (unordered for equality). All are called collections." + }, + { + "item_id": "ai-example-2", + "card_id": "w2-lists-and-sets", + "topic": "Lists and Sets", + "subtopic_id": "w2-lists-and-sets-core", + "subtopic_title": "Sequences, Uniqueness, and Common Operations", + "item_type": "ai_example", + "bucket": "aiExamples", + "selection_kind": "direct", + "search_text": "Set operations\ncountries = set() # empty set (NOT {})\ncountries = {'Andorra', 'Belgium'}\nprint({1,2,2} == {2,1}) # True (duplicates ignored)\nprint(len({1,2,2})) # 2\ncountries.remove('Andorra')\ncountries.add('Greece')\ncountries.update({'Spain', 'Italy'})\nUnordered collection of unique values. Empty set MUST be set() \u2014 {} creates empty dict. Elements must be immutable. No indexing. Methods: .add(), .remove(), .update()." + }, + { + "item_id": "ai-example-3", + "card_id": "w2-lists-and-sets", + "topic": "Lists and Sets", + "subtopic_id": "w2-lists-and-sets-core", + "subtopic_title": "Sequences, Uniqueness, and Common Operations", + "item_type": "ai_example", + "bucket": "aiExamples", + "selection_kind": "direct", + "search_text": "Create a list literal\nsquares = [1, 4, 9, 16]\nprint(squares)" + }, + { + "item_id": "ai-example-4", + "card_id": "w2-lists-and-sets", + "topic": "Lists and Sets", + "subtopic_id": "w2-lists-and-sets-core", + "subtopic_title": "Sequences, Uniqueness, and Common Operations", + "item_type": "ai_example", + "bucket": "aiExamples", + "selection_kind": "direct", + "search_text": "Delete by index with `del`\nsquares = [1, 4, 5, 9, 16]\ndel(squares[2])\nprint(squares)" + }, + { + "item_id": "ai-example-5", + "card_id": "w2-lists-and-sets", + "topic": "Lists and Sets", + "subtopic_id": "w2-lists-and-sets-core", + "subtopic_title": "Sequences, Uniqueness, and Common Operations", + "item_type": "ai_example", + "bucket": "aiExamples", + "selection_kind": "direct", + "search_text": "Two ways to create an empty list\nsquares = []\nprint(squares)\nsquares = list()\nprint(squares)" + }, + { + "item_id": "ai-example-6", + "card_id": "w2-lists-and-sets", + "topic": "Lists and Sets", + "subtopic_id": "w2-lists-and-sets-core", + "subtopic_title": "Sequences, Uniqueness, and Common Operations", + "item_type": "ai_example", + "bucket": "aiExamples", + "selection_kind": "direct", + "search_text": "Lists are mutable: replace by index\nsquares = [1, 4, 8, 15]\nsquares[2] = 9\nsquares[3] = 16\nprint(squares)" + }, + { + "item_id": "ai-example-7", + "card_id": "w2-lists-and-sets", + "topic": "Lists and Sets", + "subtopic_id": "w2-lists-and-sets-core", + "subtopic_title": "Sequences, Uniqueness, and Common Operations", + "item_type": "ai_example", + "bucket": "aiExamples", + "selection_kind": "direct", + "search_text": "List method effects and resulting list\nsquares = [1, 4, 9, 16]\nsquares.append(16)\nsquares.append(25)\nprint(squares)\nCheck whether the method mutates the list in place and what the list looks like after each call." + }, + { + "item_id": "ai-example-8", + "card_id": "w2-lists-and-sets", + "topic": "Lists and Sets", + "subtopic_id": "w2-lists-and-sets-core", + "subtopic_title": "Sequences, Uniqueness, and Common Operations", + "item_type": "ai_example", + "bucket": "aiExamples", + "selection_kind": "direct", + "search_text": "List method effects and resulting list\nif 16 not in squares:\n squares.append(16)\nif 25 not in squares:\n squares.append(25) \nprint(squares)\nCheck whether the method mutates the list in place and what the list looks like after each call." + }, + { + "item_id": "exam-Resit 22/23-1-w2-lists-and-sets", + "card_id": "w2-lists-and-sets", + "topic": "Lists and Sets", + "subtopic_id": "", + "subtopic_title": "", + "item_type": "source_exam", + "bucket": "recommended", + "selection_kind": "source", + "search_text": "Suppose you have a list called x containing tuples. Which of the following lines of code will print True?\na\nb\nc\nd\nd\nOption A evaluates to 2 * 3 == 6 (True). Option B evaluates to 3 + 5 == 8 (True). Option C evaluates to 7 - 5 == 2 (True). Therefore, all lines print True." + }, + { + "item_id": "exam-Test Resit - Introduction to Python - 22/23-1-w2-lists-and-sets", + "card_id": "w2-lists-and-sets", + "topic": "Lists and Sets", + "subtopic_id": "", + "subtopic_title": "", + "item_type": "source_exam", + "bucket": "recommended", + "selection_kind": "source", + "search_text": "Suppose you have a list called x containing tuples, where\nx = [(1, 2), (3, 4), (5, 6), (7, 8)]\n\nWhich of the following lines of code will print True?\na\nb\nc\nd\nd\nOption A evaluates to 2 * 3 == 6 (True). Option B evaluates to 3 + 5 == 8 (True). Option C evaluates to 7 - 5 == 2 (True). Therefore, all lines print True." + }, + { + "item_id": "exam-Test Resit - Introduction to Python - 22/23-5-w2-lists-and-sets", + "card_id": "w2-lists-and-sets", + "topic": "Lists and Sets", + "subtopic_id": "", + "subtopic_title": "", + "item_type": "source_exam", + "bucket": "recommended", + "selection_kind": "source", + "search_text": "Suppose you have a list called x, where:\n\nWhich of the following code segments will print the following list?\n[5, 4, 3, 2, 1]\na\nb\nc\nd\nc\nOption A creates a set (removing duplicates) and sorts it in reverse order, yielding [5, 4, 3, 2, 1]. Option B uses slicing to step backwards by 2 elements at a time, picking the second instance of each number in reverse order, which also yields [5, 4, 3, 2, 1]. Both work." + }, + { + "item_id": "exam-trial-final-exam-py22-7-w2-lists-and-sets", + "card_id": "w2-lists-and-sets", + "topic": "Lists and Sets", + "subtopic_id": "", + "subtopic_title": "", + "item_type": "source_exam", + "bucket": "recommended", + "selection_kind": "source", + "search_text": "What is the output of the following code segment?\na\nb\nc\nd\nc\nThe list comprehension filters numbers that are even (x % 2 == 0) and greater than 2 (x > 2). From the list, only 4 satisfies both conditions." + }, + { + "item_id": "exam-midterm_2023-15-w2-lists-and-sets", + "card_id": "w2-lists-and-sets", + "topic": "Lists and Sets", + "subtopic_id": "", + "subtopic_title": "", + "item_type": "source_exam", + "bucket": "recommended", + "selection_kind": "source", + "search_text": "Assume you already have a variable a, which is an integer between 1 and 4.\nWhat is the \u200boutput of the following \u200bcode snippet?" + }, + { + "item_id": "exam-midterm_2023-16-w2-lists-and-sets", + "card_id": "w2-lists-and-sets", + "topic": "Lists and Sets", + "subtopic_id": "", + "subtopic_title": "", + "item_type": "source_exam", + "bucket": "recommended", + "selection_kind": "source", + "search_text": "Consider the following code snippet:\nmylist = [1, 3, 2, 3, 4, 5, 3, 3]\nmylist.append('3')\nmylist.remove(3)\nprint(mylist.count(3))\nWhat will be the output?\nHint: The remove() list method removes the first occurrence of the element with the specified value.\nA 3\nB 4\nC 0\nD None of the given options." + }, + { + "item_id": "exam-midterm_2024-22-w2-lists-and-sets", + "card_id": "w2-lists-and-sets", + "topic": "Lists and Sets", + "subtopic_id": "", + "subtopic_title": "", + "item_type": "source_exam", + "bucket": "recommended", + "selection_kind": "source", + "search_text": "Consider the following code snippet:\nx = [\"a\", \"b\", \"c\", \"4\"]\nprint(x[-3] + x[3]*3)\nWhich of the following code snippet will print the same output?\nA z = [[\"a\", \"b\", \"c\"], [1, 2, 3, 4]]\nprint(z[0][1] + str(z[1][3])*3)\nB print('b'+ str(8 % 4)*3)\nC print('b' + str(len(x)*3))\nD y = [1, 2, 3, 4]\nprint('b'+ max(y)*3)" + }, + { + "item_id": "exam-midterm_2024-23-w2-lists-and-sets", + "card_id": "w2-lists-and-sets", + "topic": "Lists and Sets", + "subtopic_id": "", + "subtopic_title": "", + "item_type": "source_exam", + "bucket": "recommended", + "selection_kind": "source", + "search_text": "Consider the following code snippet:\nmylist = [1, 2, 5, 7, 9, 12]\nnew_list1 = mylist[0:3]\nnew_list2 = mylist[1:4]\nprint(new_list1 + new_list2)\nWhat will be printed?\nA [1, 2, 5, 2, 5, 7]\nB [1, 2, 5, 7, 2, 5, 7, 9]\nC [2, 5, 7, 5, 7, 9]\nD [2, 5, 5, 7]" + }, + { + "item_id": "ks-4258f15a6c", + "card_id": "w2-lists-and-sets", + "topic": "Lists and Sets", + "subtopic_id": "", + "subtopic_title": "", + "item_type": "source_lecture", + "bucket": "recommended", + "selection_kind": "source", + "search_text": "Lists vs Dictionaries vs Sets \u2014 ordered/unordered\nLists, tuples, strings are SEQUENCES (ordered). Dicts and sets are NOT sequences (unordered for equality). All are called collections.\nOrdering comparison\nprint([1,2] == [2,1]) # False (ordered)\nprint((1,2) == (2,1)) # False (ordered)\nprint('12' == '21') # False (ordered)\nprint({1,2} == {2,1}) # True (unordered)\nprint({1:1,2:2}=={2:2,1:1}) # True (unordered)" + }, + { + "item_id": "ks-08ac820c2f", + "card_id": "w2-lists-and-sets", + "topic": "Lists and Sets", + "subtopic_id": "", + "subtopic_title": "", + "item_type": "source_lecture", + "bucket": "recommended", + "selection_kind": "source", + "search_text": "Sets\nUnordered collection of unique values. Empty set MUST be set() \u2014 {} creates empty dict. Elements must be immutable. No indexing. Methods: .add(), .remove(), .update().\nSet operations\ncountries = set() # empty set (NOT {})\ncountries = {'Andorra', 'Belgium'}\nprint({1,2,2} == {2,1}) # True (duplicates ignored)\nprint(len({1,2,2})) # 2\ncountries.remove('Andorra')\ncountries.add('Greece')\ncountries.update({'Spain', 'Italy'})" + }, + { + "item_id": "exam-midterm_2024-24-w2-lists-and-sets", + "card_id": "w2-lists-and-sets", + "topic": "Lists and Sets", + "subtopic_id": "", + "subtopic_title": "", + "item_type": "source_exam", + "bucket": "additional", + "selection_kind": "source", + "search_text": "You have the following list:\nmy_list = [1,2,3,4]\nWhich one of the following lines of code lines does not print 4 as the output?\nA print(max(my_list))\nB print(len(my_list))\nC print(my_list[4])\nD print(my_list[-1])" + }, + { + "item_id": "exam-extra_practice-1-w2-lists-and-sets", + "card_id": "w2-lists-and-sets", + "topic": "Lists and Sets", + "subtopic_id": "", + "subtopic_title": "", + "item_type": "source_exam", + "bucket": "additional", + "selection_kind": "source", + "search_text": "Suppose you have the following function:\n\ndef func1(l1):\n return len(list(l1))==len(set(l1))\n\nWhich of the functions below returns the same values as the function above, if we call it in any of the following ways?\n\nfunc1(l1 = [1,2,3])\nfunc1(l1 = [1,2,2])\nfunc1(l1 = (1,2,2))\na\nb\nc\nd\nd\nOption a: for (1,2,2), tuple has no .count() \u2014 wait, actually tuples DO have .count(). For [1,2,2]: element 2 has count>1 so counter=2, returns False. Original returns False. But for a tuple (1,2,2): tuple has .count(), works. But option b: l1[l1.index(element)+1:] \u2014 tuples support slicing and indexing too. Let's re-examine: for a tuple (1,2,2), both a and b should work the same. Actually option a counts ALL duplicated elements (counts 2 twice for [1,2,2]), making counter=2, so counter==0 is False. Original is False too. Both match. For option b applied to tuple: l1[l1.index(element)+1:] works for tuples too. Actually both a and b return same values as original. Correct: d." + }, + { + "item_id": "manual-bool-precedence", + "card_id": "w2-conditions", + "topic": "Conditions", + "subtopic_id": "", + "subtopic_title": "", + "item_type": "ai_common_question", + "bucket": "aiQuestions", + "selection_kind": "direct", + "search_text": "How do `not`, `and`, and `or` combine when there are no extra parentheses?\n`not` is evaluated first, then `and`, then `or`, so parenthesize whenever the intended logic is not obvious.\nprint(not False and True or False)" + }, + { + "item_id": "manual-filter-condition", + "card_id": "w2-conditions", + "topic": "Conditions", + "subtopic_id": "", + "subtopic_title": "", + "item_type": "ai_common_question", + "bucket": "aiQuestions", + "selection_kind": "direct", + "search_text": "Trace `main(lst, condition)` and identify which values satisfy `lambda x: x % 2 != 0`.\nApply the condition to one element first, then keep only the values for which it returns `True`.\ndef main(lst, condition):\n return [x for x in lst if condition(x)]" + }, + { + "item_id": "manual-conditional-expression", + "card_id": "w2-conditions", + "topic": "Conditions", + "subtopic_id": "", + "subtopic_title": "", + "item_type": "ai_common_question", + "bucket": "aiQuestions", + "selection_kind": "direct", + "search_text": "When should you use `x if cond else y` instead of a multi-line `if/else` block?\nUse the conditional expression for a single value choice; use a full block when each branch needs multiple statements.\nlabel = 'pass' if score >= 10 else 'fail'" + }, + { + "item_id": "kp-manual-precedence", + "card_id": "w2-conditions", + "topic": "Conditions", + "subtopic_id": "", + "subtopic_title": "", + "item_type": "key_point", + "bucket": "keyPoints", + "selection_kind": "direct", + "search_text": "`not` binds tighter than `and`, and `and` binds tighter than `or`; add parentheses when the intended grouping is not obvious." + }, + { + "item_id": "kp-manual-ternary", + "card_id": "w2-conditions", + "topic": "Conditions", + "subtopic_id": "", + "subtopic_title": "", + "item_type": "key_point", + "bucket": "keyPoints", + "selection_kind": "direct", + "search_text": "Use `x if cond else y` when both branches are single expressions; use a full `if/elif/else` block when the branches need multiple statements." + }, + { + "item_id": "ai-example-1", + "card_id": "w2-conditions", + "topic": "Conditions", + "subtopic_id": "w2-conditions-core", + "subtopic_title": "Comparisons, `in`, Precedence, and Conditional Expressions", + "item_type": "ai_example", + "bucket": "aiExamples", + "selection_kind": "direct", + "search_text": "Precedence trap\na=1; b=3\n# WRONG: Python evaluates 'and' before 'or'\nprint(a==1 or a==2 and b==1 or b==2) # True (unexpected)\n# CORRECT: use brackets\nprint((a==1 or a==2) and (b==1 or b==2)) # False\nPrecedence (high to low): comparisons \u2192 not \u2192 and \u2192 or. Use parentheses to be explicit. 'in' checks membership in sequence/set/dict-keys.\nTrue\nFalse" + }, + { + "item_id": "ai-example-2", + "card_id": "w2-conditions", + "topic": "Conditions", + "subtopic_id": "w2-conditions-core", + "subtopic_title": "Comparisons, `in`, Precedence, and Conditional Expressions", + "item_type": "ai_example", + "bucket": "aiExamples", + "selection_kind": "direct", + "search_text": "Inclusion check \u2014 'in' operator\nprint(1 in [1,2,3]) # True\nprint(1 in (1,2,3)) # True\nprint('1' in '123') # True (substring)\nprint(1 in {1:4, 2:3}) # True (checks keys)\nprint(4 in {1:4, 2:3}) # False (4 is value, not key)\nprint(1 in {1,2,3}) # True\nPrecedence (high to low): comparisons \u2192 not \u2192 and \u2192 or. Use parentheses to be explicit. 'in' checks membership in sequence/set/dict-keys.\nTrue\nTrue\nTrue\nTrue\nFalse\nTrue" + }, + { + "item_id": "ai-example-3", + "card_id": "w2-conditions", + "topic": "Conditions", + "subtopic_id": "w2-conditions-core", + "subtopic_title": "Comparisons, `in`, Precedence, and Conditional Expressions", + "item_type": "ai_example", + "bucket": "aiExamples", + "selection_kind": "direct", + "search_text": "if/elif/else structure\nif condition_1:\n expression_1\nelif condition_2:\n expression_2\n expression_3\nelse:\n expression_4\nif/elif/else. One if at start, at most one else at end, unlimited elif in between. Indentation is critical \u2014 all code in a block must have same indentation. Conditional expression (ternary): value_if_true if condition else value_if_false." + }, + { + "item_id": "ai-example-4", + "card_id": "w2-conditions", + "topic": "Conditions", + "subtopic_id": "w2-conditions-core", + "subtopic_title": "Comparisons, `in`, Precedence, and Conditional Expressions", + "item_type": "ai_example", + "bucket": "aiExamples", + "selection_kind": "direct", + "search_text": "Conditional expression (ternary)\n# Statement form:\nif a > 0:\n b = a\nelse:\n b = 0\n# Expression form:\nb = a if a > 0 else 0\n# Even simpler:\nb = max(0, a)\nif/elif/else. One if at start, at most one else at end, unlimited elif in between. Indentation is critical \u2014 all code in a block must have same indentation. Conditional expression (ternary): value_if_true if condition else value_if_false." + }, + { + "item_id": "ai-example-5", + "card_id": "w2-conditions", + "topic": "Conditions", + "subtopic_id": "w2-conditions-core", + "subtopic_title": "Comparisons, `in`, Precedence, and Conditional Expressions", + "item_type": "ai_example", + "bucket": "aiExamples", + "selection_kind": "direct", + "search_text": "Comparison operators return booleans\nprint(3 > 2)\nA comparison like `3 > 2` evaluates to either `True` or `False`.\nTrue" + }, + { + "item_id": "ai-example-8", + "card_id": "w2-conditions", + "topic": "Conditions", + "subtopic_id": "w2-conditions-core", + "subtopic_title": "Comparisons, `in`, Precedence, and Conditional Expressions", + "item_type": "ai_example", + "bucket": "aiExamples", + "selection_kind": "direct", + "search_text": "`not` flips booleans\nprint(not True) \nprint(not False)\n`not True` becomes `False` and `not False` becomes `True`.\nFalse\nTrue" + }, + { + "item_id": "exam-Test Exam 07-06-22-4-w2-conditions", + "card_id": "w2-conditions", + "topic": "Conditions", + "subtopic_id": "", + "subtopic_title": "", + "item_type": "source_exam", + "bucket": "recommended", + "selection_kind": "source", + "search_text": "You're trying to write a function called is_anagram, which takes two strings as inputs and checks whether they are anagrams of each other. That is: whether one of them can be written by rearranging the letters of the other. Upper case and lower case versions of a letter count as the same letter, and whitespace characters don't count at all.\n\nFor example, the following function calls should all return the boolean value True:\nis_anagram(\"Old West Action\", \"Clint Eastwood\")\nis_anagram(\"eleven plus two\", \"twelve plus one\")\nis_anagram(\"I am a weakish speller\", \"William Shakespeare\")\n\nwhile the following function call should return the boolean value False:\nis_anagram(\"one plus two\", \"three\")\n\nWhich of the following code segments achieves what you want?\na\nb\nc\nd\na\nOption A correctly removes spaces, converts to lowercase, lists characters, sorts them, and compares the results. Option B and C use .sort() which returns None, and D uses .replace() on a list." + }, + { + "item_id": "exam-midterm_2023-1-w2-conditions", + "card_id": "w2-conditions", + "topic": "Conditions", + "subtopic_id": "", + "subtopic_title": "", + "item_type": "source_exam", + "bucket": "recommended", + "selection_kind": "source", + "search_text": "What is the output of the following code snippet?" + }, + { + "item_id": "exam-midterm_2024-2-w2-conditions", + "card_id": "w2-conditions", + "topic": "Conditions", + "subtopic_id": "", + "subtopic_title": "", + "item_type": "source_exam", + "bucket": "recommended", + "selection_kind": "source", + "search_text": "Assume you have the following variables:\nx = 3\ny = 3.0\nz = '3'\nWhat will be printed by the following code:\nprint((x != z and x == int(z)) or (x != y and y != z))\nA True\nB False\nC The code will result in an error.\nD 3" + }, + { + "item_id": "exam-trial_midterm-6-w2-conditions", + "card_id": "w2-conditions", + "topic": "Conditions", + "subtopic_id": "", + "subtopic_title": "", + "item_type": "source_exam", + "bucket": "recommended", + "selection_kind": "source", + "search_text": "Consider the following code snippet:\ndef main(lst, condition=lambda x: x):\ny = []\nfor x in lst:\nif condition(x):\ny.append(x)\nreturn y\nWhat will this function return, when called in the following way:\nmain([1, 2, 3, 4, 5, 6, 7, 8, 9, 10], lambda x: x % 2 != 0)\nA [2, 4, 6, 8, 10]\nB [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]\nC [1, 3, 5, 7, 9]\nD None" + }, + { + "item_id": "exam-trial_midterm-13-w2-conditions", + "card_id": "w2-conditions", + "topic": "Conditions", + "subtopic_id": "", + "subtopic_title": "", + "item_type": "source_exam", + "bucket": "recommended", + "selection_kind": "source", + "search_text": "You need to write a function called weather_alert that accepts a string argument, which is a color code of the weather\nalert system." + }, + { + "item_id": "ks-4b427a2425", + "card_id": "w2-conditions", + "topic": "Conditions", + "subtopic_id": "", + "subtopic_title": "", + "item_type": "source_lecture", + "bucket": "recommended", + "selection_kind": "source", + "search_text": "Conditions and boolean operators \u2014 precedence\nPrecedence (high to low): comparisons \u2192 not \u2192 and \u2192 or. Use parentheses to be explicit. 'in' checks membership in sequence/set/dict-keys.\nPrecedence trap\na=1; b=3\n# WRONG: Python evaluates 'and' before 'or'\nprint(a==1 or a==2 and b==1 or b==2) # True (unexpected)\n# CORRECT: use brackets\nprint((a==1 or a==2) and (b==1 or b==2)) # False\nInclusion check \u2014 'in' operator\nprint(1 in [1,2,3]) # True\nprint(1 in (1,2,3)) # True\nprint('1' in '123') # True (substring)\nprint(1 in {1:4, 2:3}) # True (checks keys)\nprint(4 in {1:4, 2:3}) # False (4 is value, not key)\nprint(1 in {1,2,3}) # True" + }, + { + "item_id": "ks-c19999c074", + "card_id": "w2-conditions", + "topic": "Conditions", + "subtopic_id": "", + "subtopic_title": "", + "item_type": "source_lecture", + "bucket": "recommended", + "selection_kind": "source", + "search_text": "Conditional statements and expressions\nif/elif/else. One if at start, at most one else at end, unlimited elif in between. Indentation is critical \u2014 all code in a block must have same indentation. Conditional expression (ternary): value_if_true if condition else value_if_false.\nif/elif/else structure\nif condition_1:\n expression_1\nelif condition_2:\n expression_2\n expression_3\nelse:\n expression_4\nConditional expression (ternary)\n# Statement form:\nif a > 0:\n b = a\nelse:\n b = 0\n# Expression form:\nb = a if a > 0 else 0\n# Even simpler:\nb = max(0, a)" + }, + { + "item_id": "manual-loop-translate", + "card_id": "w2-loops", + "topic": "Loops", + "subtopic_id": "", + "subtopic_title": "", + "item_type": "ai_common_question", + "bucket": "aiQuestions", + "selection_kind": "direct", + "search_text": "Translate `alphabet[1::2]` into a loop that collects every second character starting at index 1.\nInitialize an empty result, loop over the needed indices, and append the selected characters in order.\nresult = ''\nfor i in range(1, len(alphabet), 2):\n result += alphabet[i]" + }, + { + "item_id": "manual-break-continue", + "card_id": "w2-loops", + "topic": "Loops", + "subtopic_id": "", + "subtopic_title": "", + "item_type": "ai_common_question", + "bucket": "aiQuestions", + "selection_kind": "direct", + "search_text": "What is the difference between `break` and `continue` inside a loop?\n`break` exits the loop immediately; `continue` skips the rest of the current iteration and moves to the next one.\nfor x in data:\n if x < 0:\n continue\n if x == 0:\n break" + }, + { + "item_id": "manual-enumerate-zip", + "card_id": "w2-loops", + "topic": "Loops", + "subtopic_id": "", + "subtopic_title": "", + "item_type": "ai_common_question", + "bucket": "aiQuestions", + "selection_kind": "direct", + "search_text": "When do you reach for `enumerate` versus `zip`?\nUse `enumerate(seq)` when you need index and value together; use `zip(a, b)` when you need items from multiple iterables in parallel.\nfor i, value in enumerate(seq):\n ...\nfor left, right in zip(a, b):\n ..." + }, + { + "item_id": "kp-manual-loop-core", + "card_id": "w2-loops", + "topic": "Loops", + "subtopic_id": "", + "subtopic_title": "", + "item_type": "key_point", + "bucket": "keyPoints", + "selection_kind": "direct", + "search_text": "Use `for` when you already have an iterable; use `while` when repetition should continue only while a condition stays `True`." + }, + { + "item_id": "kp-manual-break-continue", + "card_id": "w2-loops", + "topic": "Loops", + "subtopic_id": "", + "subtopic_title": "", + "item_type": "key_point", + "bucket": "keyPoints", + "selection_kind": "direct", + "search_text": "`break` exits the loop immediately; `continue` skips the rest of the current iteration and moves to the next one." + }, + { + "item_id": "kp-manual-enumerate", + "card_id": "w2-loops", + "topic": "Loops", + "subtopic_id": "", + "subtopic_title": "", + "item_type": "key_point", + "bucket": "keyPoints", + "selection_kind": "direct", + "search_text": "`enumerate(seq, start)` gives `(index, value)` pairs; `zip(a, b)` gives tuples of items from multiple iterables in parallel." + }, + { + "item_id": "kp-manual-while-truthy", + "card_id": "w2-loops", + "topic": "Loops", + "subtopic_id": "", + "subtopic_title": "", + "item_type": "key_point", + "bucket": "keyPoints", + "selection_kind": "direct", + "search_text": "A `while` condition is checked before every iteration, so a list loop like `while items:` keeps going only while the list is non-empty." + }, + { + "item_id": "ai-example-2", + "card_id": "w2-loops", + "topic": "Loops", + "subtopic_id": "w2-loops-core", + "subtopic_title": "for, while, Dictionary Iteration, enumerate(), zip(), and Walrus", + "item_type": "ai_example", + "bucket": "aiExamples", + "selection_kind": "direct", + "search_text": "Skip certain values with `continue`\ntotal = 0\nfor number in [1, 2, '3', 3, 5, 7]:\n if type(number) == str:\n continue\n total += number\nprint(total) # 18\nUse `continue` to ignore the current item and jump straight to the next iteration.\n18" + }, + { + "item_id": "ai-example-3", + "card_id": "w2-loops", + "topic": "Loops", + "subtopic_id": "w2-loops-core", + "subtopic_title": "for, while, Dictionary Iteration, enumerate(), zip(), and Walrus", + "item_type": "ai_example", + "bucket": "aiExamples", + "selection_kind": "direct", + "search_text": "Loop variable not used \u2014 use _\nfor _ in range(5):\n print('Hello') # prints Hello 5 times\nUse `_` when the loop should repeat a fixed number of times but the loop variable itself is not needed.\nHello\nHello\nHello\nHello\nHello" + }, + { + "item_id": "ai-example-4", + "card_id": "w2-loops", + "topic": "Loops", + "subtopic_id": "w2-loops-core", + "subtopic_title": "for, while, Dictionary Iteration, enumerate(), zip(), and Walrus", + "item_type": "ai_example", + "bucket": "aiExamples", + "selection_kind": "direct", + "search_text": "`enumerate(seq, start=1)`\ncountries = ['Andorra', 'Belgium']\nfor index, country in enumerate(countries, 1):\n print(country, 'has index:', index)\n# Andorra has index: 1\n# Belgium has index: 2\nUse `enumerate` when you need both index and value, and set `start=1` if the numbering should begin at 1.\nAndorra has index: 1\nBelgium has index: 2" + }, + { + "item_id": "ai-example-5", + "card_id": "w2-loops", + "topic": "Loops", + "subtopic_id": "w2-loops-core", + "subtopic_title": "for, while, Dictionary Iteration, enumerate(), zip(), and Walrus", + "item_type": "ai_example", + "bucket": "aiExamples", + "selection_kind": "direct", + "search_text": "`zip(a, b)` pairs items in parallel\ncountries = ['Andorra', 'Belgium']\ncapitals = ['Andorra la Vella', 'Brussels']\nfor country, capital in zip(countries, capitals):\n print(country, 'has capital:', capital)\nUse `zip` when two sequences should be processed position by position together.\nAndorra has capital: Andorra la Vella\nBelgium has capital: Brussels" + }, + { + "item_id": "ai-example-7", + "card_id": "w2-loops", + "topic": "Loops", + "subtopic_id": "w2-loops-core", + "subtopic_title": "for, while, Dictionary Iteration, enumerate(), zip(), and Walrus", + "item_type": "ai_example", + "bucket": "aiExamples", + "selection_kind": "direct", + "search_text": "`while items:` repeats until the list is empty\nl1 = [1, 2, 3, 4, 5, 6]\ntotal = 0\nwhile l1: # truthy while list is non-empty\n total += l1[0]\n del l1[0]\nprint(total) # 21\nNon-empty lists are truthy and empty lists are falsy, so `while items:` is a common consume-until-empty loop.\n21" + }, + { + "item_id": "manual-loop-max-sublist-sum", + "card_id": "w2-loops", + "topic": "Loops", + "subtopic_id": "w2-loops-core", + "subtopic_title": "for, while, Dictionary Iteration, enumerate(), zip(), and Walrus", + "item_type": "ai_example", + "bucket": "aiExamples", + "selection_kind": "direct", + "search_text": "Keep the sub-list whose elements have the largest sum\nlists = [[1, 2], [4, 4], [3, 3, 1]]\nbest = lists[0]\nfor current in lists[1:]:\n if sum(current) > sum(best):\n best = current\nprint(best)\nStore the current best sub-list, compare `sum(current)` with `sum(best)` on each iteration, and update the winner when you find a larger total.\n[4, 4]" + }, + { + "item_id": "exam-intro_python_sample_final_24_25-14-w2-loops", + "card_id": "w2-loops", + "topic": "Loops", + "subtopic_id": "", + "subtopic_title": "", + "item_type": "source_exam", + "bucket": "recommended", + "selection_kind": "source", + "search_text": "Choose the program that iterates over integers from 1 to 10 and prints the sum of the current and previous number (starting with 0 as previous).\nA\nB\nC\nD\nB\nOption B correctly updates the 'previous' state at the end of each iteration to match the logic of the target output." + }, + { + "item_id": "exam-Test Resit - Introduction to Python - 22/23-4-w2-loops", + "card_id": "w2-loops", + "topic": "Loops", + "subtopic_id": "", + "subtopic_title": "", + "item_type": "source_exam", + "bucket": "recommended", + "selection_kind": "source", + "search_text": "Suppose you have the following function, which takes two integers as arguments:\n\nWhat will be printed by the following line of code:\nprint(main(1))\na\nb\nc\nd\nb\nThe function uses y=11 as a default argument. The while loop runs while i < 11 (from 1 to 10) and appends formatted strings to the list, resulting in 10 elements." + }, + { + "item_id": "exam-midterm_2023-2-w2-loops", + "card_id": "w2-loops", + "topic": "Loops", + "subtopic_id": "", + "subtopic_title": "", + "item_type": "source_exam", + "bucket": "recommended", + "selection_kind": "source", + "search_text": "What is the output of the following code snippet?" + }, + { + "item_id": "exam-midterm_2024-3-w2-loops", + "card_id": "w2-loops", + "topic": "Loops", + "subtopic_id": "", + "subtopic_title": "", + "item_type": "source_exam", + "bucket": "recommended", + "selection_kind": "source", + "search_text": "Consider the following code snippet:\ni = 1\nwhile True:\nif i % 2 == 0:\ni += 1\ncontinue\nelif i == 7:\nbreak\nelse:\nprint(i)\ni += 1\nWhich of the following code snippets will print the same output?\nA for i in range(1, 5, 2):\nprint(i)\nB for i in range(7, 1, -2):\nprint(i)\nC x = 'numbers'\nfor i, j in enumerate(x):\nif i % 2 != 0:\nprint(i)\nD x = '12345'\nfor i in x:\nif i % 2 != 0:\nprint(i)" + }, + { + "item_id": "exam-trial_midterm-5-w2-loops", + "card_id": "w2-loops", + "topic": "Loops", + "subtopic_id": "", + "subtopic_title": "", + "item_type": "source_exam", + "bucket": "recommended", + "selection_kind": "source", + "search_text": "Consider the following code snippet:\ni = 1\nwhile True:\nif i % 2 == 0:\ni += 1\ncontinue\nelif i == 7:\nbreak\nelse:\nprint(i)\ni += 1\nWhich of the following code snippets will print the same output?\nA for i in range(1, 5, 2):\nprint(i)\nB x = 'numbers'\nfor i, j in enumerate(x):\nif i % 2 != 0:\nprint(i)\nC x = '12345'\nfor i in x:\nif i % 2 != 0:\nprint(i)\nD for i in range(7, 1, -2):\nprint(i)" + }, + { + "item_id": "exam-midterm_2023-14-w2-loops", + "card_id": "w2-loops", + "topic": "Loops", + "subtopic_id": "", + "subtopic_title": "", + "item_type": "source_exam", + "bucket": "recommended", + "selection_kind": "source", + "search_text": "Assume you already have a variable called alphabet, which contains a string, e.g., alphabet = \"abcdefghijklmnopqrstuvwxyz\"\nWhich of the following code snippets will give the same output as the following command?\nprint(list(alphabet[1::2]))\nHint: The reverse() method reverses the sorting order of the elements in a list.\nA values = []\nfor index, value in enumerate(alphabet, start=1):\nif index % 2 == 0:\nvalues.append(value)\nprint(values)\nB values = []\nfor index, value in enumerate(alphabet[::-1]):\nif index % 2 == 0:\nvalues.append(value)\nvalues.reverse()\nprint(values)\nC Both of the given options.\nD None of the given options." + }, + { + "item_id": "ks-72c9eada91", + "card_id": "w2-loops", + "topic": "Loops", + "subtopic_id": "", + "subtopic_title": "", + "item_type": "source_lecture", + "bucket": "recommended", + "selection_kind": "source", + "search_text": "Augmented assignment operators\nShorthand for a = a OP b. All arithmetic operators have an augmented form.\nAll augmented operators\na += 1 # a = a + 1\na -= 2 # a = a - 2\na *= 3 # a = a * 3\na /= 4 # a = a / 4\na //= 5 # a = a // 5\na %= 6 # a = a % 6" + }, + { + "item_id": "ks-bddafc66a0", + "card_id": "w2-loops", + "topic": "Loops", + "subtopic_id": "", + "subtopic_title": "", + "item_type": "source_lecture", + "bucket": "recommended", + "selection_kind": "source", + "search_text": "For-loops\nfor variable in sequence: expression. break: exit loop entirely. continue: skip to next iteration. You don't have to use the loop variable; use _ as convention when not needed.\nFor-loop with continue\ntotal = 0\nfor number in [1, 2, '3', 3, 5, 7]:\n if type(number) == str:\n continue\n total += number\nprint(total) # 18\nLoop variable not used \u2014 use _\nfor _ in range(5):\n print('Hello') # prints Hello 5 times" + }, + { + "item_id": "ks-59aaf6b0ee", + "card_id": "w2-loops", + "topic": "Loops", + "subtopic_id": "", + "subtopic_title": "", + "item_type": "source_lecture", + "bucket": "recommended", + "selection_kind": "source", + "search_text": "enumerate()\nProvides index alongside value when looping. enumerate(seq, start) \u2014 second arg sets the start index (default 0).\nenumerate with start=1\ncountries = ['Andorra', 'Belgium']\nfor index, country in enumerate(countries, 1):\n print(country, 'has index:', index)\n# Andorra has index: 1\n# Belgium has index: 2" + }, + { + "item_id": "ks-4c6274845e", + "card_id": "w2-loops", + "topic": "Loops", + "subtopic_id": "", + "subtopic_title": "", + "item_type": "source_lecture", + "bucket": "recommended", + "selection_kind": "source", + "search_text": "zip()\nLoops over multiple sequences in parallel. Zips sequences of equal length (Python handles unequal lengths but it can be messy). Can zip sequences of different types. Can zip more than 2.\nzip two lists\ncountries = ['Andorra', 'Belgium']\ncapitals = ['Andorra la Vella', 'Brussels']\nfor country, capital in zip(countries, capitals):\n print(country, 'has capital:', capital)" + }, + { + "item_id": "exam-midterm_2024-9-w2-loops", + "card_id": "w2-loops", + "topic": "Loops", + "subtopic_id": "", + "subtopic_title": "", + "item_type": "source_exam", + "bucket": "additional", + "selection_kind": "source", + "search_text": "Suppose you have a dictionary called characters, of which keys are strings and values are lists of strings." + }, + { + "item_id": "exam-midterm_2024-17-w2-loops", + "card_id": "w2-loops", + "topic": "Loops", + "subtopic_id": "", + "subtopic_title": "", + "item_type": "source_exam", + "bucket": "additional", + "selection_kind": "source", + "search_text": "Suppose you have the following function which take a list of numerical strings as an argument." + }, + { + "item_id": "exam-midterm_2024-18-w2-loops", + "card_id": "w2-loops", + "topic": "Loops", + "subtopic_id": "", + "subtopic_title": "", + "item_type": "source_exam", + "bucket": "additional", + "selection_kind": "source", + "search_text": "Suppose you have the following function count_characters, which takes two arguments:\na list of strings which are names, and\nan optional keyword argument called character that has a default value of 'a'.\ndef count_character(x, character='a'):\ny = {}\nfor key in x:\ncount = 0\nfor char in key:\nif char == character:\ncount += 1\ny[key] = count\nreturn y\nWhat would be returned by this function, if we call the function twice as follows:\ncount_character(['Emma', 'Julia', 'Ian', 'Noah', 'Liam', 'Anna'], 'i')\ncount_character(['Emma', 'Julia', 'Ian', 'Noah', 'Liam', 'Anna'])\nA {'Emma': 0, 'Julia': 1, 'Ian': 0, 'Noah': 0, 'Liam': 1, 'Anna': 0}\n{'Emma': 1, 'Julia': 1, 'Ian': 1, 'Noah': 1, 'Liam': 1, 'Anna': 1}\nB {'Emma': 0, 'Julia': 1, 'Ian': 0, 'Noah': 0, 'Liam': 1, 'Anna': 0}\n{'Emma': 0, 'Julia': 0, 'Ian': 0, 'Noah': 0, 'Liam': 0, 'Anna': 0}\nC The first function call will result in an error because there are too many arguments.\nD The second function call will result in an error because there is a missing argument." + }, + { + "item_id": "exam-midterm_2024-20-w2-loops", + "card_id": "w2-loops", + "topic": "Loops", + "subtopic_id": "", + "subtopic_title": "", + "item_type": "source_exam", + "bucket": "additional", + "selection_kind": "source", + "search_text": "What is the output of the program below?" + }, + { + "item_id": "exam-midterm_2024-21-w2-loops", + "card_id": "w2-loops", + "topic": "Loops", + "subtopic_id": "", + "subtopic_title": "", + "item_type": "source_exam", + "bucket": "additional", + "selection_kind": "source", + "search_text": "Assume you already have a variable called x, which contains a list of integers.\nWhich of the following programs will print you a list of the squared values of the elements in x?" + }, + { + "item_id": "ks-8ad541fef7", + "card_id": "w2-loops", + "topic": "Loops", + "subtopic_id": "", + "subtopic_title": "", + "item_type": "source_lecture", + "bucket": "additional", + "selection_kind": "source", + "search_text": "While-loops\nwhile condition: expression. Checks condition BEFORE each execution. Use break and continue. Watch for infinite loops (Ctrl+C to exit). Use when you don't know beforehand how many iterations are needed. For-loops can always be replaced by while-loops.\nWhile with break/continue\ntotal = 0\nwhile True:\n number = int(input('give a number, or 100 to stop '))\n if number == 100:\n break\n if number % 2 == 0:\n continue\n total += number\nprint(total)\nTruthy/Falsy in while condition\nl1 = [1, 2, 3, 4, 5, 6]\ntotal = 0\nwhile l1: # truthy while list is non-empty\n total += l1[0]\n del l1[0]\nprint(total) # 21" + }, + { + "item_id": "ks-624034d573", + "card_id": "w2-loops", + "topic": "Loops", + "subtopic_id": "", + "subtopic_title": "", + "item_type": "source_lecture", + "bucket": "additional", + "selection_kind": "source", + "search_text": "Walrus operator :=\nIntroduced in Python 3.8. Assigns AND evaluates to a value (unlike = which is a statement). Useful in while conditions to assign and test at once.\nWalrus in while loop\ntotal = 0\nwhile (number := int(input('give a number, or 100 to stop '))) != 100:\n if number % 2 == 1:\n total += number\nprint(total)" + }, + { + "item_id": "kp-1", + "card_id": "w2-conversion-and-truthiness", + "topic": "Conversion and Truthiness", + "subtopic_id": "w2-conversion-and-truthiness-core", + "subtopic_title": "Explicit Conversion and Truthy/Falsy Rules", + "item_type": "key_point", + "bucket": "keyPoints", + "selection_kind": "direct", + "search_text": "In conditions, Python auto-converts to bool. Falsy: [], (), {}, set(), '', 0, 0.0, range(0), None. Truthy: everything else (non-empty collections, non-zero numbers)." + }, + { + "item_id": "kp-1-d1", + "card_id": "w2-conversion-and-truthiness", + "topic": "Conversion and Truthiness", + "subtopic_id": "", + "subtopic_title": "", + "item_type": "key_point_detail", + "bucket": "keyPoints", + "selection_kind": "detail", + "search_text": "Falsy values\n# All evaluate to False in a condition:\n[] # empty list\n() # empty tuple\n{} # empty dict\nset() # empty set\n'' # empty string\n0 # zero int\n0.0 # zero float" + }, + { + "item_id": "kp-2", + "card_id": "w2-conversion-and-truthiness", + "topic": "Conversion and Truthiness", + "subtopic_id": "w2-conversion-and-truthiness-core", + "subtopic_title": "Explicit Conversion and Truthy/Falsy Rules", + "item_type": "key_point", + "bucket": "keyPoints", + "selection_kind": "direct", + "search_text": "Python requires explicit conversion in most cases (unlike JavaScript). Conversion functions: str(), int(), float(), bool(), tuple(), list(), set(), dict()." + }, + { + "item_id": "kp-2-d1", + "card_id": "w2-conversion-and-truthiness", + "topic": "Conversion and Truthiness", + "subtopic_id": "", + "subtopic_title": "", + "item_type": "key_point_detail", + "bucket": "keyPoints", + "selection_kind": "detail", + "search_text": "Explicit conversions\nprint(str(1) == '1') # True\nprint(int('1') == 1) # True\nprint(int('1a')) # ERROR\nprint(float('1') == 1.0) # True\nprint(float('1.0') == 1.0) # True\nprint(tuple([1,2,3]) == (1,2,3)) # True\nprint(tuple({1:3, 2:4}) == (1,2)) # True (dict->tuple gives keys)\nprint(list(range(1,5,2)) == [1,3]) # True\nprint(dict([1, 2])) # ERROR\nprint(dict([(1,3),(2,4)]) == {1:3, 2:4}) # True" + }, + { + "item_id": "kp-2-d2", + "card_id": "w2-conversion-and-truthiness", + "topic": "Conversion and Truthiness", + "subtopic_id": "", + "subtopic_title": "", + "item_type": "key_point_detail", + "bucket": "keyPoints", + "selection_kind": "detail", + "search_text": "Implicit conversion (Python allows with bool/numeric mix)\nprint(1 + True) # 2\nprint(1.0 + False) # 1.0\nprint('1' * 2) # '11'\nprint('1' * True) # '1'\nprint('1' * False) # ''" + }, + { + "item_id": "ai-example-1", + "card_id": "w2-conversion-and-truthiness", + "topic": "Conversion and Truthiness", + "subtopic_id": "w2-conversion-and-truthiness-core", + "subtopic_title": "Explicit Conversion and Truthy/Falsy Rules", + "item_type": "ai_example", + "bucket": "aiExamples", + "selection_kind": "direct", + "search_text": "Falsy values\n# All evaluate to False in a condition:\n[] # empty list\n() # empty tuple\n{} # empty dict\nset() # empty set\n'' # empty string\n0 # zero int\n0.0 # zero float\nIn conditions, Python auto-converts to bool. Falsy: [], (), {}, set(), '', 0, 0.0, range(0), None. Truthy: everything else (non-empty collections, non-zero numbers)." + }, + { + "item_id": "ai-example-2", + "card_id": "w2-conversion-and-truthiness", + "topic": "Conversion and Truthiness", + "subtopic_id": "w2-conversion-and-truthiness-core", + "subtopic_title": "Explicit Conversion and Truthy/Falsy Rules", + "item_type": "ai_example", + "bucket": "aiExamples", + "selection_kind": "direct", + "search_text": "Explicit conversions\nprint(str(1) == '1') # True\nprint(int('1') == 1) # True\nprint(int('1a')) # ERROR\nprint(float('1') == 1.0) # True\nprint(float('1.0') == 1.0) # True\nprint(tuple([1,2,3]) == (1,2,3)) # True\nprint(tuple({1:3, 2:4}) == (1,2)) # True (dict->tuple gives keys)\nprint(list(range(1,5,2)) == [1,3]) # True\nprint(dict([1, 2])) # ERROR\nprint(dict([(1,3),(2,4)]) == {1:3, 2:4}) # True\nPython requires explicit conversion in most cases (unlike JavaScript). Conversion functions: str(), int(), float(), bool(), tuple(), list(), set(), dict()." + }, + { + "item_id": "ai-example-3", + "card_id": "w2-conversion-and-truthiness", + "topic": "Conversion and Truthiness", + "subtopic_id": "w2-conversion-and-truthiness-core", + "subtopic_title": "Explicit Conversion and Truthy/Falsy Rules", + "item_type": "ai_example", + "bucket": "aiExamples", + "selection_kind": "direct", + "search_text": "Implicit conversion (Python allows with bool/numeric mix)\nprint(1 + True) # 2\nprint(1.0 + False) # 1.0\nprint('1' * 2) # '11'\nprint('1' * True) # '1'\nprint('1' * False) # ''\nPython requires explicit conversion in most cases (unlike JavaScript). Conversion functions: str(), int(), float(), bool(), tuple(), list(), set(), dict()." + }, + { + "item_id": "ai-example-4", + "card_id": "w2-conversion-and-truthiness", + "topic": "Conversion and Truthiness", + "subtopic_id": "w2-conversion-and-truthiness-core", + "subtopic_title": "Explicit Conversion and Truthy/Falsy Rules", + "item_type": "ai_example", + "bucket": "aiExamples", + "selection_kind": "direct", + "search_text": "str(1) versus int('1')\nprint(str(1) == '1')\nprint(int('1') == 1)" + }, + { + "item_id": "ai-example-5", + "card_id": "w2-conversion-and-truthiness", + "topic": "Conversion and Truthiness", + "subtopic_id": "w2-conversion-and-truthiness-core", + "subtopic_title": "Explicit Conversion and Truthy/Falsy Rules", + "item_type": "ai_example", + "bucket": "aiExamples", + "selection_kind": "direct", + "search_text": "Why `'1' + 2` raises `TypeError`\ntry:\n print ('1' + 2)\nexcept Exception as e:\n print(e)" + }, + { + "item_id": "ai-example-6", + "card_id": "w2-conversion-and-truthiness", + "topic": "Conversion and Truthiness", + "subtopic_id": "w2-conversion-and-truthiness-core", + "subtopic_title": "Explicit Conversion and Truthy/Falsy Rules", + "item_type": "ai_example", + "bucket": "aiExamples", + "selection_kind": "direct", + "search_text": "Why `dict([1, 2])` raises `ValueError`\ntry:\n print(dict([1, 2]))\nexcept Exception as e:\n print(e)" + }, + { + "item_id": "ai-example-7", + "card_id": "w2-conversion-and-truthiness", + "topic": "Conversion and Truthiness", + "subtopic_id": "w2-conversion-and-truthiness-core", + "subtopic_title": "Explicit Conversion and Truthy/Falsy Rules", + "item_type": "ai_example", + "bucket": "aiExamples", + "selection_kind": "direct", + "search_text": "Why `int('1a')` raises `ValueError`\ntry:\n print(int('1a') == 1)\nexcept Exception as e:\n print(e)" + }, + { + "item_id": "ai-example-8", + "card_id": "w2-conversion-and-truthiness", + "topic": "Conversion and Truthiness", + "subtopic_id": "w2-conversion-and-truthiness-core", + "subtopic_title": "Explicit Conversion and Truthy/Falsy Rules", + "item_type": "ai_example", + "bucket": "aiExamples", + "selection_kind": "direct", + "search_text": "Truthy list in a `while` condition\nl1 = [1, 2, 3, 4, 5, 6]\ntotal = 0\nwhile l1:\n total += l1[0]\n del l1[0]\nprint(total)\nFor numeric variables, `a += 1` updates the stored value the same way as `a = a + 1`." + }, + { + "item_id": "ks-d7e6d1b5b5", + "card_id": "w2-conversion-and-truthiness", + "topic": "Conversion and Truthiness", + "subtopic_id": "", + "subtopic_title": "", + "item_type": "source_lecture", + "bucket": "recommended", + "selection_kind": "source", + "search_text": "Truthy and Falsy\nIn conditions, Python auto-converts to bool. Falsy: [], (), {}, set(), '', 0, 0.0, range(0), None. Truthy: everything else (non-empty collections, non-zero numbers).\nFalsy values\n# All evaluate to False in a condition:\n[] # empty list\n() # empty tuple\n{} # empty dict\nset() # empty set\n'' # empty string\n0 # zero int\n0.0 # zero float" + }, + { + "item_id": "ks-d9760d8cd8", + "card_id": "w2-conversion-and-truthiness", + "topic": "Conversion and Truthiness", + "subtopic_id": "", + "subtopic_title": "", + "item_type": "source_lecture", + "bucket": "recommended", + "selection_kind": "source", + "search_text": "Type conversion (explicit)\nPython requires explicit conversion in most cases (unlike JavaScript). Conversion functions: str(), int(), float(), bool(), tuple(), list(), set(), dict().\nExplicit conversions\nprint(str(1) == '1') # True\nprint(int('1') == 1) # True\nprint(int('1a')) # ERROR\nprint(float('1') == 1.0) # True\nprint(float('1.0') == 1.0) # True\nprint(tuple([1,2,3]) == (1,2,3)) # True\nprint(tuple({1:3, 2:4}) == (1,2)) # True (dict->tuple gives keys)\nprint(list(range(1,5,2)) == [1,3]) # True\nprint(dict([1, 2])) # ERROR\nprint(dict([(1,3),(2,4)]) == {1:3, 2:4}) # True\nImplicit conversion (Python allows with bool/numeric mix)\nprint(1 + True) # 2\nprint(1.0 + False) # 1.0\nprint('1' * 2) # '11'\nprint('1' * True) # '1'\nprint('1' * False) # ''" + }, + { + "item_id": "cs-fc8bdeb969", + "card_id": "w2-conversion-and-truthiness", + "topic": "Conversion and Truthiness", + "subtopic_id": "", + "subtopic_title": "", + "item_type": "source_notebook", + "bucket": "additional", + "selection_kind": "source", + "search_text": "type_conversion\nprint (1==1.0, 1.0 == True, 0 == False)" + }, + { + "item_id": "cs-3e39a2f12f", + "card_id": "w2-conversion-and-truthiness", + "topic": "Conversion and Truthiness", + "subtopic_id": "", + "subtopic_title": "", + "item_type": "source_notebook", + "bucket": "additional", + "selection_kind": "source", + "search_text": "type_conversion\nprint ('1' * 2, '1' * True, '1' * False)" + }, + { + "item_id": "manual-call-vs-index", + "card_id": "w3-defining-and-calling-functions", + "topic": "Defining and Calling Functions", + "subtopic_id": "", + "subtopic_title": "", + "item_type": "ai_common_question", + "bucket": "aiQuestions", + "selection_kind": "direct", + "search_text": "What error do you get from `print[1]` and from `[1, 2, 3](0)`?\n`print[1]` tries to subscript a function, while `[1, 2, 3](0)` tries to call a list. Both raise `TypeError`, but for opposite reasons.\nprint[1]\n[1, 2, 3](0)" + }, + { + "item_id": "manual-string-return-shape", + "card_id": "w3-defining-and-calling-functions", + "topic": "Defining and Calling Functions", + "subtopic_id": "", + "subtopic_title": "", + "item_type": "ai_common_question", + "bucket": "aiQuestions", + "selection_kind": "direct", + "search_text": "How do you recognize that a function should `return` a string instead of `print` it?\nIf the result must be reused later, the function should `return` the string so the caller can store, combine, or print it afterwards.\ndef get_tld(url):\n parts = url.split('.')\n return parts[-1].split('/')[0]" + }, + { + "item_id": "manual-list-of-dicts-loop", + "card_id": "w3-defining-and-calling-functions", + "topic": "Defining and Calling Functions", + "subtopic_id": "", + "subtopic_title": "", + "item_type": "ai_common_question", + "bucket": "aiQuestions", + "selection_kind": "direct", + "search_text": "How do you access values when looping over a list of dictionaries?\nEach loop iteration gives one dictionary, so read fields with keys like `student['Name']` and `student['Grade']`.\nfor student in students:\n print(student['Name'], student['Grade'])" + }, + { + "item_id": "kp-1", + "card_id": "w3-defining-and-calling-functions", + "topic": "Defining and Calling Functions", + "subtopic_id": "w3-defining-and-calling-functions-core", + "subtopic_title": "def, Calls, and Methods vs Functions", + "item_type": "key_point", + "bucket": "keyPoints", + "selection_kind": "direct", + "search_text": "Define with `def name(params):` and call with `()`. `f[3]` tries to index, while `lst(0)` tries to call a list and raises `TypeError`." + }, + { + "item_id": "kp-1-d1", + "card_id": "w3-defining-and-calling-functions", + "topic": "Defining and Calling Functions", + "subtopic_id": "", + "subtopic_title": "", + "item_type": "key_point_detail", + "bucket": "keyPoints", + "selection_kind": "detail", + "search_text": "Basic function\ndef adder(n1, n2):\n total = n1 + n2\n return total\na = adder(1, 2)\nprint(a) # 3" + }, + { + "item_id": "kp-1-d2", + "card_id": "w3-defining-and-calling-functions", + "topic": "Defining and Calling Functions", + "subtopic_id": "", + "subtopic_title": "", + "item_type": "key_point_detail", + "bucket": "keyPoints", + "selection_kind": "detail", + "search_text": "Wrong bracket errors\nprint[1] # TypeError: 'function' object is not subscriptable\nl1 = [1,2,3]\nl1(1) # TypeError: 'list' object is not callable" + }, + { + "item_id": "kp-2", + "card_id": "w3-defining-and-calling-functions", + "topic": "Defining and Calling Functions", + "subtopic_id": "w3-defining-and-calling-functions-core", + "subtopic_title": "def, Calls, and Methods vs Functions", + "item_type": "key_point", + "bucket": "keyPoints", + "selection_kind": "direct", + "search_text": "Methods are functions attached to objects. Some mutate the object in place, while others return a value; string methods always return a new string." + }, + { + "item_id": "kp-2-d1", + "card_id": "w3-defining-and-calling-functions", + "topic": "Defining and Calling Functions", + "subtopic_id": "", + "subtopic_title": "", + "item_type": "key_point_detail", + "bucket": "keyPoints", + "selection_kind": "detail", + "search_text": "Method on immutable \u2014 must capture return value\ns1 = 'UVA Amsterdam'\ns1 = s1.upper() # CORRECT \u2014 captures new string\ns1.upper() # WRONG \u2014 result is lost, s1 unchanged" + }, + { + "item_id": "kp-2-d2", + "card_id": "w3-defining-and-calling-functions", + "topic": "Defining and Calling Functions", + "subtopic_id": "", + "subtopic_title": "", + "item_type": "key_point_detail", + "bucket": "keyPoints", + "selection_kind": "detail", + "search_text": "Method on mutable \u2014 changes in place vs returns value\nl1 = [3, 1, 2]\nl1.sort() # changes l1 in place, returns None\nprint(l1) # [1, 2, 3]\nprint(l1.index(2)) # 1 (returns index, doesn't change l1)" + }, + { + "item_id": "kp-3", + "card_id": "w3-defining-and-calling-functions", + "topic": "Defining and Calling Functions", + "subtopic_id": "w3-defining-and-calling-functions-core", + "subtopic_title": "def, Calls, and Methods vs Functions", + "item_type": "key_point", + "bucket": "keyPoints", + "selection_kind": "direct", + "search_text": "Function skeleton: `def f(x): return result`. Define with `def ...`, call with `()`, and use `[]` only for indexing." + }, + { + "item_id": "ai-example-1", + "card_id": "w3-defining-and-calling-functions", + "topic": "Defining and Calling Functions", + "subtopic_id": "w3-defining-and-calling-functions-core", + "subtopic_title": "def, Calls, and Methods vs Functions", + "item_type": "ai_example", + "bucket": "aiExamples", + "selection_kind": "direct", + "search_text": "Define, call, and return a value\ndef adder(n1, n2):\n total = n1 + n2\n return total\na = adder(1, 2)\nprint(a) # 3\nDefine with `def name(params):` and call with `()`. `f[3]` tries to index, while `lst(0)` tries to call a list and raises `TypeError`.\n3" + }, + { + "item_id": "ai-example-2", + "card_id": "w3-defining-and-calling-functions", + "topic": "Defining and Calling Functions", + "subtopic_id": "w3-defining-and-calling-functions-core", + "subtopic_title": "def, Calls, and Methods vs Functions", + "item_type": "ai_example", + "bucket": "aiExamples", + "selection_kind": "direct", + "search_text": "Wrong bracket errors\nprint[1] # TypeError: 'function' object is not subscriptable\nl1 = [1,2,3]\nl1(1) # TypeError: 'list' object is not callable\nDefine with `def name(params):` and call with `()`. `f[3]` tries to index, while `lst(0)` tries to call a list and raises `TypeError`.\nTypeError\nTypeError" + }, + { + "item_id": "ai-example-3", + "card_id": "w3-defining-and-calling-functions", + "topic": "Defining and Calling Functions", + "subtopic_id": "w3-defining-and-calling-functions-core", + "subtopic_title": "def, Calls, and Methods vs Functions", + "item_type": "ai_example", + "bucket": "aiExamples", + "selection_kind": "direct", + "search_text": "Method on immutable \u2014 must capture return value\ns1 = 'UVA Amsterdam'\ns1 = s1.upper() # CORRECT \u2014 captures new string\ns1.upper() # WRONG \u2014 result is lost, s1 unchanged\nMethods are functions attached to objects. Some mutate the object in place, while others return a value; string methods always return a new string.\nUVA AMSTERDAM" + }, + { + "item_id": "ai-example-4", + "card_id": "w3-defining-and-calling-functions", + "topic": "Defining and Calling Functions", + "subtopic_id": "w3-defining-and-calling-functions-core", + "subtopic_title": "def, Calls, and Methods vs Functions", + "item_type": "ai_example", + "bucket": "aiExamples", + "selection_kind": "direct", + "search_text": "Method on mutable \u2014 changes in place vs returns value\nl1 = [3, 1, 2]\nl1.sort() # changes l1 in place, returns None\nprint(l1) # [1, 2, 3]\nprint(l1.index(2)) # 1 (returns index, doesn't change l1)\nMethods are functions attached to objects. Some mutate the object in place, while others return a value; string methods always return a new string.\n[1, 2, 3]\n1" + }, + { + "item_id": "exam-intro_python_sample_final_24_25-3-w3-defining-and-calling-functions", + "card_id": "w3-defining-and-calling-functions", + "topic": "Defining and Calling Functions", + "subtopic_id": "", + "subtopic_title": "", + "item_type": "source_exam", + "bucket": "recommended", + "selection_kind": "source", + "search_text": "Imagine that you have a list called students, which is populated by a number of dictionaries. Each dictionary has keys: \"Name\" and \"Grade\". You'd like to print the text: [NAME] has received a grade of [GRADE], with the grade displayed to one decimal place. Which of the following code segments will achieve what you want?\nA\nB\nC\nD\nA\nWhen iterating over a list of dictionaries, each iteration yields a dictionary. You access values using keys like student['Name']. Options B and D fail because lists do not have an .items() method." + }, + { + "item_id": "exam-intro_python_sample_final_24_25-11-w3-defining-and-calling-functions", + "card_id": "w3-defining-and-calling-functions", + "topic": "Defining and Calling Functions", + "subtopic_id": "", + "subtopic_title": "", + "item_type": "source_exam", + "bucket": "recommended", + "selection_kind": "source", + "search_text": "Which of the following code lines will create a dictionary, in which the keys are the elements of list_1 and the values are the number of characters in the corresponding key?\nA\nB\nC\nD\nA\nThis is a standard dictionary comprehension. Option B is a list comprehension, Option C is a set comprehension, and Option D swaps keys and values." + }, + { + "item_id": "exam-intro_python_sample_final_24_25-17-w3-defining-and-calling-functions", + "card_id": "w3-defining-and-calling-functions", + "topic": "Defining and Calling Functions", + "subtopic_id": "", + "subtopic_title": "", + "item_type": "source_exam", + "bucket": "recommended", + "selection_kind": "source", + "search_text": "What will be printed by the function calls in the main function provided?\nA\nB\nC\nD\nD\nThe function checks if all elements in the input list are either all empty or all non-empty. For the sets and lists provided, they are consistent within each call." + }, + { + "item_id": "exam-Test Exam 07-06-22-3-w3-defining-and-calling-functions", + "card_id": "w3-defining-and-calling-functions", + "topic": "Defining and Calling Functions", + "subtopic_id": "", + "subtopic_title": "", + "item_type": "source_exam", + "bucket": "recommended", + "selection_kind": "source", + "search_text": "You would like to write a function called get_tld that extracts the top-level domain from the URL of a website. The function takes the URL as the input string in the following format:\n\"https://www.[SECOND-LEVEL DOMAIN].[TOP-LEVEL DOMAIN]/[FOLDER 1]/[...]/[FOLDER N]/[PAGE NAME].html\"\nand returns the top-level domain as a string.\n\nFor example, the function call:\nget_tld(\"https://www.uva.nl/en/education/bachelor-s/bachelors.html\")\nshould return the string:\n\"nl\"\n\nWhich of the following code segments would not achieve what you want?\na\nb\nc\nd\na\nOption A splits the entire URL by '.', so the last element will be 'html' (from 'bachelors.html'). Then splitting 'html' by '/' and taking the first element still results in 'html', not the top-level domain 'nl'. Therefore, it does NOT achieve what is intended." + }, + { + "item_id": "exam-Trial final exam Introduction to Python-4-w3-defining-and-calling-functions", + "card_id": "w3-defining-and-calling-functions", + "topic": "Defining and Calling Functions", + "subtopic_id": "", + "subtopic_title": "", + "item_type": "source_exam", + "bucket": "recommended", + "selection_kind": "source", + "search_text": "You need to write a function called format_phone_number that formats phone numbers. The output of the function should be a string that represents a 10-digit number. The input argument is also a string with 10 digits, but the digits may be separated by dashes (the \"-\" character) at various places.\n\nFor example, the following function calls:\nformat_phone_number(\"020-525-1400\")\nformat_phone_number(\"020-5251400\")\nformat_phone_number(\"020-525-14-00\")\nshould all return the string:\n\"0205251400\"\n\nWhich of the following code segments does not achieve what you want?\na\nb\nc\nd\na\nStrings in Python are immutable. The `replace()` method returns a new string, it does not modify the original string in place. Because Option A does not reassign the result of `number.replace(\"-\", \"\")` or return it directly, it returns the original, unmodified string." + }, + { + "item_id": "exam-Test Exam 07-06-22-4-w3-defining-and-calling-functions", + "card_id": "w3-defining-and-calling-functions", + "topic": "Defining and Calling Functions", + "subtopic_id": "", + "subtopic_title": "", + "item_type": "source_exam", + "bucket": "recommended", + "selection_kind": "source", + "search_text": "You're trying to write a function called is_anagram, which takes two strings as inputs and checks whether they are anagrams of each other. That is: whether one of them can be written by rearranging the letters of the other. Upper case and lower case versions of a letter count as the same letter, and whitespace characters don't count at all.\n\nFor example, the following function calls should all return the boolean value True:\nis_anagram(\"Old West Action\", \"Clint Eastwood\")\nis_anagram(\"eleven plus two\", \"twelve plus one\")\nis_anagram(\"I am a weakish speller\", \"William Shakespeare\")\n\nwhile the following function call should return the boolean value False:\nis_anagram(\"one plus two\", \"three\")\n\nWhich of the following code segments achieves what you want?\na\nb\nc\nd\na\nOption A correctly removes spaces, converts strings to lower case, transforms them to lists, and sorts the lists using sorted() before comparing them. Option B is incorrect because strings do not have a .sort() method. Option C is incorrect because list.sort() operates in-place and returns None, so it would compare None == None. Option D is incorrect because sorted() returns a list, and lists do not have a .replace() or .lower() method." + }, + { + "item_id": "ks-e09d7f145b", + "card_id": "w3-defining-and-calling-functions", + "topic": "Defining and Calling Functions", + "subtopic_id": "", + "subtopic_title": "", + "item_type": "source_lecture", + "bucket": "recommended", + "selection_kind": "source", + "search_text": "Function definition and calling\ndef keyword, function name, parameters in parentheses, colon, indented body. Call with round brackets (). Using [] gives TypeError 'not subscriptable'. Using [] on a list with () gives TypeError 'not callable'.\nBasic function\ndef adder(n1, n2):\n total = n1 + n2\n return total\na = adder(1, 2)\nprint(a) # 3\nWrong bracket errors\nprint[1] # TypeError: 'function' object is not subscriptable\nl1 = [1,2,3]\nl1(1) # TypeError: 'list' object is not callable" + }, + { + "item_id": "ks-ab66f3bab6", + "card_id": "w3-defining-and-calling-functions", + "topic": "Defining and Calling Functions", + "subtopic_id": "", + "subtopic_title": "", + "item_type": "source_lecture", + "bucket": "recommended", + "selection_kind": "source", + "search_text": "Methods vs functions\nMethods are functions attached to objects. Calling obj.method() is equivalent to Class.method(obj). For mutable objects: some methods CHANGE the object (e.g. list.sort()), some RETURN a value (e.g. list.index()). For immutable objects: methods always return a new value (can't change the object itself). COMMON ERROR: s1.upper() on strings \u2014 you must do s1 = s1.upper() to save the result.\nMethod on immutable \u2014 must capture return value\ns1 = 'UVA Amsterdam'\ns1 = s1.upper() # CORRECT \u2014 captures new string\ns1.upper() # WRONG \u2014 result is lost, s1 unchanged\nMethod on mutable \u2014 changes in place vs returns value\nl1 = [3, 1, 2]\nl1.sort() # changes l1 in place, returns None\nprint(l1) # [1, 2, 3]\nprint(l1.index(2)) # 1 (returns index, doesn't change l1)" + }, + { + "item_id": "aiq-1", + "card_id": "w3-return-behavior", + "topic": "Return Behavior", + "subtopic_id": "", + "subtopic_title": "", + "item_type": "ai_common_question", + "bucket": "aiQuestions", + "selection_kind": "direct", + "search_text": "Condition flow and branch result\nExam \u2022 midterm_2024 \u2022 Q1\nConsider the following code snippet:\na = True\nb = False\nc = True\nd = False\nif not (a or b) and (c or d):\nprint(\"True\")\nelse:\nprint(\"False\")\nWhat will be printed by the code?" + }, + { + "item_id": "aiq-2", + "card_id": "w3-return-behavior", + "topic": "Return Behavior", + "subtopic_id": "", + "subtopic_title": "", + "item_type": "ai_common_question", + "bucket": "aiQuestions", + "selection_kind": "direct", + "search_text": "def multiply(num1, num2):\nmultiply() has no return statement, so it returns None. print(multiply(2,3)) prints None. But inside, global result is set to 6. print(result) prints 6. Output: None, 6.\nExam \u2022 extra_practice \u2022 Q7" + }, + { + "item_id": "aiq-3", + "card_id": "w3-return-behavior", + "topic": "Return Behavior", + "subtopic_id": "", + "subtopic_title": "", + "item_type": "ai_common_question", + "bucket": "aiQuestions", + "selection_kind": "direct", + "search_text": "Assume sum_even_in_list(l1) filters non-integers and sums even integers.\na: *args creates a tuple, sum_even_in_list accepts any iterable so passing a tuple works. b: list comprehension on tuple works fine. c: direct iteration over tuple works. All three produce the same result. Correct: d.\nExam \u2022 extra_practice \u2022 Q9" + }, + { + "item_id": "aiq-4", + "card_id": "w3-return-behavior", + "topic": "Return Behavior", + "subtopic_id": "", + "subtopic_title": "", + "item_type": "ai_common_question", + "bucket": "aiQuestions", + "selection_kind": "direct", + "search_text": "Implicit return None\nFunction without return statement, or where return is not reached, returns None. print(func()) will print None." + }, + { + "item_id": "aiq-5", + "card_id": "w3-return-behavior", + "topic": "Return Behavior", + "subtopic_id": "", + "subtopic_title": "", + "item_type": "ai_common_question", + "bucket": "aiQuestions", + "selection_kind": "direct", + "search_text": "Single-element tuple needs trailing comma\n(1) is int, not tuple. (1,) or 1, is a tuple" + }, + { + "item_id": "kp-1", + "card_id": "w3-return-behavior", + "topic": "Return Behavior", + "subtopic_id": "w3-return-behavior-core", + "subtopic_title": "return, Implicit None, Multiple Returns, pass, and Single-Element Tuples", + "item_type": "key_point", + "bucket": "keyPoints", + "selection_kind": "direct", + "search_text": "Returns a value to the caller. If you don't capture the return value it's lost. A function leaves no traces \u2014 local names are gone after function ends. Common error: using print() instead of return in homework functions." + }, + { + "item_id": "kp-1-d1", + "card_id": "w3-return-behavior", + "topic": "Return Behavior", + "subtopic_id": "", + "subtopic_title": "", + "item_type": "key_point_detail", + "bucket": "keyPoints", + "selection_kind": "detail", + "search_text": "Returning a tuple (multiple values)\ndef powers(n1):\n return n1 ** 2, n1 ** 3 # returns a tuple\npower2, power3 = powers(3)\nprint(power2, power3) # 9 27" + }, + { + "item_id": "kp-2", + "card_id": "w3-return-behavior", + "topic": "Return Behavior", + "subtopic_id": "w3-return-behavior-core", + "subtopic_title": "return, Implicit None, Multiple Returns, pass, and Single-Element Tuples", + "item_type": "key_point", + "bucket": "keyPoints", + "selection_kind": "direct", + "search_text": "If a function reaches the end without a return statement, Python returns None automatically. This is bad practice but you must know it. Test with: if a != None: or if a is not None:" + }, + { + "item_id": "kp-2-d1", + "card_id": "w3-return-behavior", + "topic": "Return Behavior", + "subtopic_id": "", + "subtopic_title": "", + "item_type": "key_point_detail", + "bucket": "keyPoints", + "selection_kind": "detail", + "search_text": "Implicit None return\ndef adder(n1, n2):\n if type(n1) == type(n2) == int:\n total = n1 + n2\n return total\na = adder('1', 2) # Returns None (no return hit)\nprint(a) # None" + }, + { + "item_id": "kp-3", + "card_id": "w3-return-behavior", + "topic": "Return Behavior", + "subtopic_id": "w3-return-behavior-core", + "subtopic_title": "return, Implicit None, Multiple Returns, pass, and Single-Element Tuples", + "item_type": "key_point", + "bucket": "keyPoints", + "selection_kind": "direct", + "search_text": "(1) is NOT a tuple \u2014 it's just the integer 1. To create a 1-element tuple: t = (1,) or t = 1,. Neat swap trick: x, y = y, x" + }, + { + "item_id": "kp-3-d1", + "card_id": "w3-return-behavior", + "topic": "Return Behavior", + "subtopic_id": "", + "subtopic_title": "", + "item_type": "key_point_detail", + "bucket": "keyPoints", + "selection_kind": "detail", + "search_text": "1-element tuple gotcha\nt1 = (1)\nprint(type(t1) == tuple) # False\nprint(type(t1) == int) # True\nt1 = (1,) # correct 1-element tuple\nt1 = 1, # also correct\nx, y = y, x # swap using tuple unpacking" + }, + { + "item_id": "kp-4", + "card_id": "w3-return-behavior", + "topic": "Return Behavior", + "subtopic_id": "w3-return-behavior-core", + "subtopic_title": "return, Implicit None, Multiple Returns, pass, and Single-Element Tuples", + "item_type": "key_point", + "bucket": "keyPoints", + "selection_kind": "direct", + "search_text": "Does nothing. Used as a placeholder when an indented block is required but you have nothing to put there yet (stub). After a colon you must have an indented block \u2014 pass satisfies this." + }, + { + "item_id": "kp-4-d1", + "card_id": "w3-return-behavior", + "topic": "Return Behavior", + "subtopic_id": "", + "subtopic_title": "", + "item_type": "key_point_detail", + "bucket": "keyPoints", + "selection_kind": "detail", + "search_text": "pass as stub\ndef adder(n1, n2):\n if type(n1) == int and type(n2) == int:\n result = n1 + n2\n else:\n pass # placeholder \u2014 won't cause IndentationError\n return result" + }, + { + "item_id": "ai-example-1", + "card_id": "w3-return-behavior", + "topic": "Return Behavior", + "subtopic_id": "w3-return-behavior-core", + "subtopic_title": "return, Implicit None, Multiple Returns, pass, and Single-Element Tuples", + "item_type": "ai_example", + "bucket": "aiExamples", + "selection_kind": "direct", + "search_text": "Returning a tuple (multiple values)\ndef powers(n1):\n return n1 ** 2, n1 ** 3 # returns a tuple\npower2, power3 = powers(3)\nprint(power2, power3) # 9 27\nReturns a value to the caller. If you don't capture the return value it's lost. A function leaves no traces \u2014 local names are gone after function ends. Common error: using print() instead of return in homework functions." + }, + { + "item_id": "ai-example-2", + "card_id": "w3-return-behavior", + "topic": "Return Behavior", + "subtopic_id": "w3-return-behavior-core", + "subtopic_title": "return, Implicit None, Multiple Returns, pass, and Single-Element Tuples", + "item_type": "ai_example", + "bucket": "aiExamples", + "selection_kind": "direct", + "search_text": "Implicit None return\ndef adder(n1, n2):\n if type(n1) == type(n2) == int:\n total = n1 + n2\n return total\na = adder('1', 2) # Returns None (no return hit)\nprint(a) # None\nIf a function reaches the end without a return statement, Python returns None automatically. This is bad practice but you must know it. Test with: if a != None: or if a is not None:" + }, + { + "item_id": "ai-example-3", + "card_id": "w3-return-behavior", + "topic": "Return Behavior", + "subtopic_id": "w3-return-behavior-core", + "subtopic_title": "return, Implicit None, Multiple Returns, pass, and Single-Element Tuples", + "item_type": "ai_example", + "bucket": "aiExamples", + "selection_kind": "direct", + "search_text": "1-element tuple gotcha\nt1 = (1)\nprint(type(t1) == tuple) # False\nprint(type(t1) == int) # True\nt1 = (1,) # correct 1-element tuple\nt1 = 1, # also correct\nx, y = y, x # swap using tuple unpacking\n(1) is NOT a tuple \u2014 it's just the integer 1. To create a 1-element tuple: t = (1,) or t = 1,. Neat swap trick: x, y = y, x" + }, + { + "item_id": "ai-example-4", + "card_id": "w3-return-behavior", + "topic": "Return Behavior", + "subtopic_id": "w3-return-behavior-core", + "subtopic_title": "return, Implicit None, Multiple Returns, pass, and Single-Element Tuples", + "item_type": "ai_example", + "bucket": "aiExamples", + "selection_kind": "direct", + "search_text": "pass as stub\ndef adder(n1, n2):\n if type(n1) == int and type(n2) == int:\n result = n1 + n2\n else:\n pass # placeholder \u2014 won't cause IndentationError\n return result\nDoes nothing. Used as a placeholder when an indented block is required but you have nothing to put there yet (stub). After a colon you must have an indented block \u2014 pass satisfies this." + }, + { + "item_id": "ai-example-5", + "card_id": "w3-return-behavior", + "topic": "Return Behavior", + "subtopic_id": "w3-return-behavior-core", + "subtopic_title": "return, Implicit None, Multiple Returns, pass, and Single-Element Tuples", + "item_type": "ai_example", + "bucket": "aiExamples", + "selection_kind": "direct", + "search_text": "Function return value and trace\ndef adder(n1, n2):\n return n1 + n2\na = adder(1,2)\nprint(a)\nTrace the returned value, not just what gets printed while the function runs." + }, + { + "item_id": "ai-example-6", + "card_id": "w3-return-behavior", + "topic": "Return Behavior", + "subtopic_id": "w3-return-behavior-core", + "subtopic_title": "return, Implicit None, Multiple Returns, pass, and Single-Element Tuples", + "item_type": "ai_example", + "bucket": "aiExamples", + "selection_kind": "direct", + "search_text": "Function return value and trace\ndef adder(n1, n2):\n total = n1 + n2\na = adder(1, 2)\nprint(a)\nTrace the returned value, not just what gets printed while the function runs." + }, + { + "item_id": "ai-example-7", + "card_id": "w3-return-behavior", + "topic": "Return Behavior", + "subtopic_id": "w3-return-behavior-core", + "subtopic_title": "return, Implicit None, Multiple Returns, pass, and Single-Element Tuples", + "item_type": "ai_example", + "bucket": "aiExamples", + "selection_kind": "direct", + "search_text": "Function return value and trace\ndef powers(n1):\n return n1 ** 2, n1 ** 3\na = powers(3)\nprint(a)\nTrace the returned value, not just what gets printed while the function runs." + }, + { + "item_id": "ai-example-8", + "card_id": "w3-return-behavior", + "topic": "Return Behavior", + "subtopic_id": "w3-return-behavior-core", + "subtopic_title": "return, Implicit None, Multiple Returns, pass, and Single-Element Tuples", + "item_type": "ai_example", + "bucket": "aiExamples", + "selection_kind": "direct", + "search_text": "Function return value and trace\ndef powers(n1):\n return n1 ** 2, n1 ** 3\npower2, power3 = powers(3)\nprint(power2, power3)\nTrace the returned value, not just what gets printed while the function runs." + }, + { + "item_id": "exam-trial-final-exam-py22-3-w3-return-behavior", + "card_id": "w3-return-behavior", + "topic": "Return Behavior", + "subtopic_id": "", + "subtopic_title": "", + "item_type": "source_exam", + "bucket": "recommended", + "selection_kind": "source", + "search_text": "What will be returned by the following code segment?\na\nb\nc\nd\na\nThe function checks if the type is exactly int. 1.0, 3.50 are floats, and '9' is a string, so they are replaced by None." + }, + { + "item_id": "exam-Resit 22/23-3-w3-return-behavior", + "card_id": "w3-return-behavior", + "topic": "Return Behavior", + "subtopic_id": "", + "subtopic_title": "", + "item_type": "source_exam", + "bucket": "recommended", + "selection_kind": "source", + "search_text": "What will be printed by the following code segment?\na\nb\nc\nd\nb\nThe function checks if the type of each element `i` in the list `x` is the same as the type of `x` (which is a list). The only element in `x` that is a list is `[]`. So, it appends `[]` to `y`, resulting in `[[]]`." + }, + { + "item_id": "exam-Trial final - Introduction to Python - 22/23-3-w3-return-behavior", + "card_id": "w3-return-behavior", + "topic": "Return Behavior", + "subtopic_id": "", + "subtopic_title": "", + "item_type": "source_exam", + "bucket": "recommended", + "selection_kind": "source", + "search_text": "What is the output of the following code segment?\na\nb\nc\nd\na\nThe types of the elements are: 'abc' is str, 0 is int, None is NoneType, True is bool, 123.456 is float, 'False' is str (since it's in quotes), and {} is dict." + }, + { + "item_id": "exam-midterm_2024-1-w3-return-behavior", + "card_id": "w3-return-behavior", + "topic": "Return Behavior", + "subtopic_id": "", + "subtopic_title": "", + "item_type": "source_exam", + "bucket": "recommended", + "selection_kind": "source", + "search_text": "Consider the following code snippet:\na = True\nb = False\nc = True\nd = False\nif not (a or b) and (c or d):\nprint(\"True\")\nelse:\nprint(\"False\")\nWhat will be printed by the code?\nA True\nB False\nC The code will result in an error.\nD None" + }, + { + "item_id": "exam-extra_practice-7-w3-return-behavior", + "card_id": "w3-return-behavior", + "topic": "Return Behavior", + "subtopic_id": "", + "subtopic_title": "", + "item_type": "source_exam", + "bucket": "recommended", + "selection_kind": "source", + "search_text": "def multiply(num1, num2):\n\tglobal result\n\tresult = num1 * num2\n\nprint(multiply(2, 3))\nprint(result)\na\nb\nc\nd\nb\nmultiply() has no return statement, so it returns None. print(multiply(2,3)) prints None. But inside, global result is set to 6. print(result) prints 6. Output: None, 6." + }, + { + "item_id": "exam-extra_practice-9-w3-return-behavior", + "card_id": "w3-return-behavior", + "topic": "Return Behavior", + "subtopic_id": "", + "subtopic_title": "", + "item_type": "source_exam", + "bucket": "recommended", + "selection_kind": "source", + "search_text": "Assume sum_even_in_list(l1) filters non-integers and sums even integers.\n\nYou want sum_even_integers that accepts a flexible number of arguments.\n\nFor example: sum_even_integers(1,'2', 3.0, 4) should return 4.\n\nWhich of the following function definitions will work as intended?\na\nb\nc\nd\nd\na: *args creates a tuple, sum_even_in_list accepts any iterable so passing a tuple works. b: list comprehension on tuple works fine. c: direct iteration over tuple works. All three produce the same result. Correct: d." + }, + { + "item_id": "ks-00b2983ca8", + "card_id": "w3-return-behavior", + "topic": "Return Behavior", + "subtopic_id": "", + "subtopic_title": "", + "item_type": "source_lecture", + "bucket": "recommended", + "selection_kind": "source", + "search_text": "Return statement\nReturns a value to the caller. If you don't capture the return value it's lost. A function leaves no traces \u2014 local names are gone after function ends. Common error: using print() instead of return in homework functions.\nReturning a tuple (multiple values)\ndef powers(n1):\n return n1 ** 2, n1 ** 3 # returns a tuple\npower2, power3 = powers(3)\nprint(power2, power3) # 9 27" + }, + { + "item_id": "ks-14515a5856", + "card_id": "w3-return-behavior", + "topic": "Return Behavior", + "subtopic_id": "", + "subtopic_title": "", + "item_type": "source_lecture", + "bucket": "recommended", + "selection_kind": "source", + "search_text": "Implicit return \u2014 None\nIf a function reaches the end without a return statement, Python returns None automatically. This is bad practice but you must know it. Test with: if a != None: or if a is not None:\nImplicit None return\ndef adder(n1, n2):\n if type(n1) == type(n2) == int:\n total = n1 + n2\n return total\na = adder('1', 2) # Returns None (no return hit)\nprint(a) # None" + }, + { + "item_id": "ks-d1a2d7739d", + "card_id": "w3-return-behavior", + "topic": "Return Behavior", + "subtopic_id": "", + "subtopic_title": "", + "item_type": "source_lecture", + "bucket": "recommended", + "selection_kind": "source", + "search_text": "Single-element tuple\n(1) is NOT a tuple \u2014 it's just the integer 1. To create a 1-element tuple: t = (1,) or t = 1,. Neat swap trick: x, y = y, x\n1-element tuple gotcha\nt1 = (1)\nprint(type(t1) == tuple) # False\nprint(type(t1) == int) # True\nt1 = (1,) # correct 1-element tuple\nt1 = 1, # also correct\nx, y = y, x # swap using tuple unpacking" + }, + { + "item_id": "ks-db93da9e3e", + "card_id": "w3-return-behavior", + "topic": "Return Behavior", + "subtopic_id": "", + "subtopic_title": "", + "item_type": "source_lecture", + "bucket": "recommended", + "selection_kind": "source", + "search_text": "pass keyword\nDoes nothing. Used as a placeholder when an indented block is required but you have nothing to put there yet (stub). After a colon you must have an indented block \u2014 pass satisfies this.\npass as stub\ndef adder(n1, n2):\n if type(n1) == int and type(n2) == int:\n result = n1 + n2\n else:\n pass # placeholder \u2014 won't cause IndentationError\n return result" + }, + { + "item_id": "manual-local-name", + "card_id": "w3-scope", + "topic": "Scope", + "subtopic_id": "", + "subtopic_title": "", + "item_type": "ai_common_question", + "bucket": "aiQuestions", + "selection_kind": "direct", + "search_text": "Why does `print(n1)` fail outside `def adder(n1, n2): ...`?\nParameter names are local to the function body, so they do not exist in the global scope after the call finishes.\ndef adder(n1, n2):\n return n1 + n2\n\nadder(1, 2)\nprint(n1)" + }, + { + "item_id": "manual-unboundlocal", + "card_id": "w3-scope", + "topic": "Scope", + "subtopic_id": "", + "subtopic_title": "", + "item_type": "ai_common_question", + "bucket": "aiQuestions", + "selection_kind": "direct", + "search_text": "Why can assigning to a name inside a function cause `UnboundLocalError`?\nIf a function assigns to a name anywhere in its body, Python treats that name as local throughout the function unless you declare it `global` or `nonlocal`.\nb = 1\n\ndef main(a):\n b = b\n return a" + }, + { + "item_id": "manual-global", + "card_id": "w3-scope", + "topic": "Scope", + "subtopic_id": "", + "subtopic_title": "", + "item_type": "ai_common_question", + "bucket": "aiQuestions", + "selection_kind": "direct", + "search_text": "When do you need `global`?\nUse `global name` only when the function should rebind a global variable; simple reads of a global name do not need it.\nn1 = 1\n\ndef changer():\n global n1\n n1 = n1 + 1" + }, + { + "item_id": "kp-manual-scope-local", + "card_id": "w3-scope", + "topic": "Scope", + "subtopic_id": "", + "subtopic_title": "", + "item_type": "key_point", + "bucket": "keyPoints", + "selection_kind": "direct", + "search_text": "Names assigned inside a function are local by default, including parameter names." + }, + { + "item_id": "kp-manual-scope-unbound", + "card_id": "w3-scope", + "topic": "Scope", + "subtopic_id": "", + "subtopic_title": "", + "item_type": "key_point", + "bucket": "keyPoints", + "selection_kind": "direct", + "search_text": "If a function assigns to a name anywhere, Python treats that name as local throughout that function unless `global` or `nonlocal` says otherwise." + }, + { + "item_id": "kp-manual-scope-global", + "card_id": "w3-scope", + "topic": "Scope", + "subtopic_id": "", + "subtopic_title": "", + "item_type": "key_point", + "bucket": "keyPoints", + "selection_kind": "direct", + "search_text": "Use `global x` only when the function should rebind the global name `x`; mutating an object passed in as an argument does not require `global`." + }, + { + "item_id": "manual-scope-local-name", + "card_id": "w3-scope", + "topic": "Scope", + "subtopic_id": "w3-scope-core", + "subtopic_title": "Global vs Local Names and Scope Errors", + "item_type": "ai_example", + "bucket": "aiExamples", + "selection_kind": "direct", + "search_text": "Parameter names stay local to the function\ndef adder(n1, n2):\n return n1 + n2\n\nprint(adder(1, 2))\nprint(n1)\nAfter the function call, `n1` and `n2` do not exist outside the function body.\n3\nNameError" + }, + { + "item_id": "manual-scope-unbound", + "card_id": "w3-scope", + "topic": "Scope", + "subtopic_id": "w3-scope-core", + "subtopic_title": "Global vs Local Names and Scope Errors", + "item_type": "ai_example", + "bucket": "aiExamples", + "selection_kind": "direct", + "search_text": "Assignment makes the name local\nb = 1\n\ndef main(a):\n b = b\n return a\n\nprint(main(1))\nBecause `b` is assigned inside `main`, Python treats it as local before the `b = b` line runs.\nUnboundLocalError" + }, + { + "item_id": "manual-scope-global-change", + "card_id": "w3-scope", + "topic": "Scope", + "subtopic_id": "w3-scope-core", + "subtopic_title": "Global vs Local Names and Scope Errors", + "item_type": "ai_example", + "bucket": "aiExamples", + "selection_kind": "direct", + "search_text": "Use `global` to rebind a global name\nn1 = 1\n\ndef changer():\n global n1\n n1 = n1 + 1\n\nchanger()\nprint(n1)\nWith `global n1`, the assignment updates the global name instead of creating a local one.\n2" + }, + { + "item_id": "manual-scope-rebind-parameter", + "card_id": "w3-scope", + "topic": "Scope", + "subtopic_id": "w3-scope-core", + "subtopic_title": "Global vs Local Names and Scope Errors", + "item_type": "ai_example", + "bucket": "aiExamples", + "selection_kind": "direct", + "search_text": "Rebinding a parameter does not change the caller's name\ndef changer(n1):\n n1 = n1 + 1\n return n1\n\na = 1\na = changer(a)\nprint(a)\nThe function works with its local parameter; the caller changes only because the returned value is assigned back to `a`.\n2" + }, + { + "item_id": "exam-intro_python_sample_final_24_25-15-w2-conditions", + "card_id": "w3-scope", + "topic": "Scope", + "subtopic_id": "", + "subtopic_title": "", + "item_type": "source_exam", + "bucket": "recommended", + "selection_kind": "source", + "search_text": "Executing the following program will produce an error. Why?\nA\nB\nC\nD\nA\nThe variable 'result' is defined inside the 'cube' function, making it local to that function. It cannot be accessed from the global scope." + }, + { + "item_id": "exam-trial-final-exam-py22-2-w3-scope", + "card_id": "w3-scope", + "topic": "Scope", + "subtopic_id": "", + "subtopic_title": "", + "item_type": "source_exam", + "bucket": "recommended", + "selection_kind": "source", + "search_text": "Take a look at the following code segment. Will executing this code segment produce an error? If yes, then why?\na\nb\nc\nd\nb\nThe global variable 'a' is accessible inside the inner function without error. The code evaluates to inner(5) * 3 = (1 + 5 + 4) * 3 = 30." + }, + { + "item_id": "exam-Resit 22/23-2-w3-scope", + "card_id": "w3-scope", + "topic": "Scope", + "subtopic_id": "", + "subtopic_title": "", + "item_type": "source_exam", + "bucket": "recommended", + "selection_kind": "source", + "search_text": "Executing the following program will produce an error. Why?\na\nb\nc\nd\na\nThe variable `result` is defined inside the `power` function, giving it local scope. It cannot be accessed outside the function in the global scope where `print(result)` is called." + }, + { + "item_id": "exam-Test Resit - Introduction to Python - 22/23-2-w3-scope", + "card_id": "w3-scope", + "topic": "Scope", + "subtopic_id": "", + "subtopic_title": "", + "item_type": "source_exam", + "bucket": "recommended", + "selection_kind": "source", + "search_text": "Executing the following program will produce an error. Why?\na\nb\nc\nd\nd\nThe variable 'result' is defined inside the scope of the 'power' function and is therefore a local variable. It cannot be accessed outside the function in the global scope." + }, + { + "item_id": "exam-Trial final - Introduction to Python - 22/23-2-w3-scope", + "card_id": "w3-scope", + "topic": "Scope", + "subtopic_id": "", + "subtopic_title": "", + "item_type": "source_exam", + "bucket": "recommended", + "selection_kind": "source", + "search_text": "Calling the function func_1() will produce an error. Which line of the following code segment produces the error?\na\nb\nc\nd\na\nvar_1 is a local variable inside func_2, so it is not accessible in the scope of func_1. Furthermore, func_2 is never called, so var_1 is never created. The code will throw an UnboundLocalError or NameError when evaluating var_1 in 'var_2 = var_1 - var'." + }, + { + "item_id": "exam-extra_practice-2-w3-scope", + "card_id": "w3-scope", + "topic": "Scope", + "subtopic_id": "", + "subtopic_title": "", + "item_type": "source_exam", + "bucket": "recommended", + "selection_kind": "source", + "search_text": "val = 2\ndef func():\n val = 3\n print(val)\nfunc()\nprint(val)\n\nWhich of the following code snippets produces the same output as the above code snippet?\na\nb\nc\nd\nc\nOriginal output: 3, 2. Option a: UnboundLocalError (val1 used before local assignment). Option b: global val2 modified to 3, print 3, then print val2=3. Output: 3,3. Option c: func3 creates local val3=3, prints 3. Global val3=2 unchanged, prints 2. Output: 3,2. Matches! Option d: innerfunc() called outside func4 scope \u2014 NameError. Correct: c." + }, + { + "item_id": "exam-midterm_2023-3-w3-scope", + "card_id": "w3-scope", + "topic": "Scope", + "subtopic_id": "", + "subtopic_title": "", + "item_type": "source_exam", + "bucket": "recommended", + "selection_kind": "source", + "search_text": "Which other program will give the same output as the following code snippet?" + }, + { + "item_id": "exam-midterm_2024-5-w3-scope", + "card_id": "w3-scope", + "topic": "Scope", + "subtopic_id": "", + "subtopic_title": "", + "item_type": "source_exam", + "bucket": "recommended", + "selection_kind": "source", + "search_text": "Which other program will produce the same output as the following code snippet?" + }, + { + "item_id": "ks-2a6510492d", + "card_id": "w3-scope", + "topic": "Scope", + "subtopic_id": "", + "subtopic_title": "", + "item_type": "source_lecture", + "bucket": "recommended", + "selection_kind": "source", + "search_text": "Global and local scope\nLocal names: defined inside a function (parameter names + any assignment inside). Only known inside the function. Global names: defined outside any function, known everywhere EXCEPT when a same-named local exists (local dominates). Python makes names local at call time, BEFORE executing the body \u2014 so if you assign to a name ANYWHERE in a function, that name is local throughout the function (even before the assignment line). Use 'global' keyword to override (but avoid it).\nLocal name not accessible outside\ndef adder(n1, n2):\n return n1 + n2\nadder(1, 2)\nprint(n1) # NameError: name 'n1' is not defined\nUnboundLocalError trap \u2014 local shadows global even before assignment\ndef main(a):\n b = b # ERROR: Python sees b assigned in function -> local\n return a # but local b has no value yet\nb = 1\nprint(main(1)) # UnboundLocalError\nglobal keyword\ndef changer():\n global n1\n n1 = n1 + 1\nn1 = 1\nchanger()\nprint(n1) # 2\nBetter pattern: avoid global\ndef changer(n1):\n n1 = n1 + 1\n return n1\na = 1\na = changer(a)\nprint(a) # 2\nMutable parameter is the SAME object\ndef adder(l2):\n result = 0\n while l2:\n result += l2.pop()\n return result\nl1 = [1, 2, 3, 4, 5]\ntotal = adder(l1)\nprint(f'The sum of {l1} = {total}') # The sum of [] = 15 !!!\n# l1 is empty because l2 and l1 refer to the SAME list object\nFix: copy mutable arg at start of function\ndef adder(l2):\n l2 = l2[:] # make a copy\n result = 0\n while l2:\n result += l2.pop()\n return result" + }, + { + "item_id": "aiq-1", + "card_id": "w3-arguments", + "topic": "Arguments", + "subtopic_id": "", + "subtopic_title": "", + "item_type": "ai_common_question", + "bucket": "aiQuestions", + "selection_kind": "direct", + "search_text": "Mutable default argument\nCheck whether the method mutates the list in place and what the list looks like after each call.\nMutable default argument" + }, + { + "item_id": "aiq-2", + "card_id": "w3-arguments", + "topic": "Arguments", + "subtopic_id": "", + "subtopic_title": "", + "item_type": "ai_common_question", + "bucket": "aiQuestions", + "selection_kind": "direct", + "search_text": "Mutable arguments\nMutating a passed list changes the caller's object; rebinding the parameter does not.\nMutable arguments" + }, + { + "item_id": "aiq-3", + "card_id": "w3-arguments", + "topic": "Arguments", + "subtopic_id": "", + "subtopic_title": "", + "item_type": "ai_common_question", + "bucket": "aiQuestions", + "selection_kind": "direct", + "search_text": "Suppose you have the following function:\nTrace the returned value, not just what gets printed while the function runs.\nExam \u2022 midterm_2023 \u2022 Q9\nSuppose you have the following function:\ndef add_numbers(num1, num2 = 10, num3 = 20):\nreturn num1 + num2 + num3\nWhat are the outputs if we call the function three times as follows:\nadd_numbers(5, 15)\nadd_numbers(5, num3 = 30)\nadd_numbers(num2 = 15, num3 = 10)" + }, + { + "item_id": "aiq-4", + "card_id": "w3-arguments", + "topic": "Arguments", + "subtopic_id": "", + "subtopic_title": "", + "item_type": "ai_common_question", + "bucket": "aiQuestions", + "selection_kind": "direct", + "search_text": "You need to write a function called print_info which takes two required arguments called name and age, and a flexible number of keyword\nCheck whether the method mutates the list in place and what the list looks like after each call.\nExam \u2022 midterm_2023 \u2022 Q10\nFor example:\nIf we call the function as:\nprint_info('John', 30, city = 'New York', job = 'software engineer')\nthen it should return the dictionary:\n{'name' = 'John', 'age' = 30, 'city' = 'New York', 'job' = 'software engineer'}\nWhich of the following code snippets will do what you want?" + }, + { + "item_id": "aiq-5", + "card_id": "w3-arguments", + "topic": "Arguments", + "subtopic_id": "", + "subtopic_title": "", + "item_type": "ai_common_question", + "bucket": "aiQuestions", + "selection_kind": "direct", + "search_text": "You have to write a function called summarize which take a list of integers as an argument.\nReturn `{'amount': len(nums), 'smallest': min(nums), 'largest': max(nums), 'total': sum(nums)}`.\nExam \u2022 midterm_2024 \u2022 Q13\nThe function should return a dictionary with the following key-value pairs:\namount: the number of the integers from the input list\nsmallest: the smallest integer from the input list\nlargest: the largest integer from the input list\ntotal: the sum of all integers from the input list\nWhich of the following functions will achieve what you need?" + }, + { + "item_id": "aiq-6", + "card_id": "w3-arguments", + "topic": "Arguments", + "subtopic_id": "", + "subtopic_title": "", + "item_type": "ai_common_question", + "bucket": "aiQuestions", + "selection_kind": "direct", + "search_text": "Mutable default argument\ndef f(lst=[]): \u2014 the [] is created ONCE at def time and persists across calls. Fix: use None and create inside function" + }, + { + "item_id": "aiq-7", + "card_id": "w3-arguments", + "topic": "Arguments", + "subtopic_id": "", + "subtopic_title": "", + "item_type": "ai_common_question", + "bucket": "aiQuestions", + "selection_kind": "direct", + "search_text": "Mutable parameter sharing\nWhen mutable object passed as argument, parameter and argument point to SAME object \u2014 mutations inside function affect original" + }, + { + "item_id": "kp-1", + "card_id": "w3-arguments", + "topic": "Arguments", + "subtopic_id": "w3-arguments-core", + "subtopic_title": "Positional, Keyword, Default, *args, **kwargs, and Mutable Argument Traps", + "item_type": "key_point", + "bucket": "keyPoints", + "selection_kind": "direct", + "search_text": "Prefixing a parameter with * makes Python collect all extra positional arguments into a tuple named args. Can mix with defined parameters: def f(n1, n2, *args) \u2014 Python fills n1,n2 first then collects remainder into args." + }, + { + "item_id": "kp-1-d1", + "card_id": "w3-arguments", + "topic": "Arguments", + "subtopic_id": "", + "subtopic_title": "", + "item_type": "key_point_detail", + "bucket": "keyPoints", + "selection_kind": "detail", + "search_text": "*args usage\ndef adder(*args):\n result = 0\n for number in args:\n result += number\n return result\nprint(adder(1, 2, 3, 4, 5)) # 15" + }, + { + "item_id": "kp-1-d2", + "card_id": "w3-arguments", + "topic": "Arguments", + "subtopic_id": "", + "subtopic_title": "", + "item_type": "key_point_detail", + "bucket": "keyPoints", + "selection_kind": "detail", + "search_text": "Mix defined and *args\ndef adder(n1, n2, *args):\n result = n1 + n2\n for number in args:\n result += number\n return result\nprint(adder(1, 2, 3, 4, 5)) # 15" + }, + { + "item_id": "kp-2", + "card_id": "w3-arguments", + "topic": "Arguments", + "subtopic_id": "w3-arguments-core", + "subtopic_title": "Positional, Keyword, Default, *args, **kwargs, and Mutable Argument Traps", + "item_type": "key_point", + "bucket": "keyPoints", + "selection_kind": "direct", + "search_text": "Arguments can be passed by name (keyword). **kwargs collects undefined keyword arguments into a dict. Order in function definition: positional, *args, keyword-with-defaults, **kwargs." + }, + { + "item_id": "kp-2-d1", + "card_id": "w3-arguments", + "topic": "Arguments", + "subtopic_id": "", + "subtopic_title": "", + "item_type": "key_point_detail", + "bucket": "keyPoints", + "selection_kind": "detail", + "search_text": "Keyword arguments\ndef calc(first, second, third, fourth, fifth, sixth):\n return first + 2*second + 3*third + 4*fourth + 5*fifth + 6*sixth\nprint(calc(fifth=2, third=4, fourth=1, sixth=5, second=2, first=3)) # 63" + }, + { + "item_id": "kp-2-d2", + "card_id": "w3-arguments", + "topic": "Arguments", + "subtopic_id": "", + "subtopic_title": "", + "item_type": "key_point_detail", + "bucket": "keyPoints", + "selection_kind": "detail", + "search_text": "**kwargs\ndef calc(**kwargs):\n return kwargs['first'] + 2*kwargs['second'] + 3*kwargs['third']\nprint(calc(third=4, second=2, first=3))" + }, + { + "item_id": "kp-3", + "card_id": "w3-arguments", + "topic": "Arguments", + "subtopic_id": "w3-arguments-core", + "subtopic_title": "Positional, Keyword, Default, *args, **kwargs, and Mutable Argument Traps", + "item_type": "key_point", + "bucket": "keyPoints", + "selection_kind": "direct", + "search_text": "Default values are part of the function HEADER (not the call). When argument is omitted, the default is used. Keyword args in a call use =. CRITICAL: mutable defaults are evaluated ONCE at def time \u2014 never use mutable defaults; use None instead." + }, + { + "item_id": "kp-3-d1", + "card_id": "w3-arguments", + "topic": "Arguments", + "subtopic_id": "", + "subtopic_title": "", + "item_type": "key_point_detail", + "bucket": "keyPoints", + "selection_kind": "detail", + "search_text": "Default value\ndef multiplier(first, second=2):\n return first * second\nprint(multiplier(3)) # 6 (uses default second=2)\nprint(multiplier(3, 3)) # 9\nprint(multiplier(2, second=3)) # 6" + }, + { + "item_id": "kp-3-d2", + "card_id": "w3-arguments", + "topic": "Arguments", + "subtopic_id": "", + "subtopic_title": "", + "item_type": "key_point_detail", + "bucket": "keyPoints", + "selection_kind": "detail", + "search_text": "Mutable default BUG\ndef main(addition, l1=[]):\n l1.append(addition)\n return l1\nprint(main(2)) # [2]\nprint(main(3)) # [2, 3] \u2190 BUG: l1 persists!" + }, + { + "item_id": "ai-example-1", + "card_id": "w3-arguments", + "topic": "Arguments", + "subtopic_id": "w3-arguments-core", + "subtopic_title": "Positional, Keyword, Default, *args, **kwargs, and Mutable Argument Traps", + "item_type": "ai_example", + "bucket": "aiExamples", + "selection_kind": "direct", + "search_text": "*args usage\ndef adder(*args):\n result = 0\n for number in args:\n result += number\n return result\nprint(adder(1, 2, 3, 4, 5)) # 15\nPrefixing a parameter with * makes Python collect all extra positional arguments into a tuple named args. Can mix with defined parameters: def f(n1, n2, *args) \u2014 Python fills n1,n2 first then collects remainder into args." + }, + { + "item_id": "ai-example-2", + "card_id": "w3-arguments", + "topic": "Arguments", + "subtopic_id": "w3-arguments-core", + "subtopic_title": "Positional, Keyword, Default, *args, **kwargs, and Mutable Argument Traps", + "item_type": "ai_example", + "bucket": "aiExamples", + "selection_kind": "direct", + "search_text": "Mix defined and *args\ndef adder(n1, n2, *args):\n result = n1 + n2\n for number in args:\n result += number\n return result\nprint(adder(1, 2, 3, 4, 5)) # 15\nPrefixing a parameter with * makes Python collect all extra positional arguments into a tuple named args. Can mix with defined parameters: def f(n1, n2, *args) \u2014 Python fills n1,n2 first then collects remainder into args." + }, + { + "item_id": "ai-example-3", + "card_id": "w3-arguments", + "topic": "Arguments", + "subtopic_id": "w3-arguments-core", + "subtopic_title": "Positional, Keyword, Default, *args, **kwargs, and Mutable Argument Traps", + "item_type": "ai_example", + "bucket": "aiExamples", + "selection_kind": "direct", + "search_text": "Keyword arguments\ndef calc(first, second, third, fourth, fifth, sixth):\n return first + 2*second + 3*third + 4*fourth + 5*fifth + 6*sixth\nprint(calc(fifth=2, third=4, fourth=1, sixth=5, second=2, first=3)) # 63\nArguments can be passed by name (keyword). **kwargs collects undefined keyword arguments into a dict. Order in function definition: positional, *args, keyword-with-defaults, **kwargs." + }, + { + "item_id": "ai-example-4", + "card_id": "w3-arguments", + "topic": "Arguments", + "subtopic_id": "w3-arguments-core", + "subtopic_title": "Positional, Keyword, Default, *args, **kwargs, and Mutable Argument Traps", + "item_type": "ai_example", + "bucket": "aiExamples", + "selection_kind": "direct", + "search_text": "Function return value and trace\ndef calc(**kwargs):\n return kwargs['first'] + 2*kwargs['second'] + 3*kwargs['third']\nprint(calc(third=4, second=2, first=3))\nArguments can be passed by name (keyword). **kwargs collects undefined keyword arguments into a dict. Order in function definition: positional, *args, keyword-with-defaults, **kwargs." + }, + { + "item_id": "ai-example-5", + "card_id": "w3-arguments", + "topic": "Arguments", + "subtopic_id": "w3-arguments-core", + "subtopic_title": "Positional, Keyword, Default, *args, **kwargs, and Mutable Argument Traps", + "item_type": "ai_example", + "bucket": "aiExamples", + "selection_kind": "direct", + "search_text": "Default value\ndef multiplier(first, second=2):\n return first * second\nprint(multiplier(3)) # 6 (uses default second=2)\nprint(multiplier(3, 3)) # 9\nprint(multiplier(2, second=3)) # 6\nDefault values are part of the function HEADER (not the call). When argument is omitted, the default is used. Keyword args in a call use =. CRITICAL: mutable defaults are evaluated ONCE at def time \u2014 never use mutable defaults; use None instead." + }, + { + "item_id": "ai-example-6", + "card_id": "w3-arguments", + "topic": "Arguments", + "subtopic_id": "w3-arguments-core", + "subtopic_title": "Positional, Keyword, Default, *args, **kwargs, and Mutable Argument Traps", + "item_type": "ai_example", + "bucket": "aiExamples", + "selection_kind": "direct", + "search_text": "Mutable default BUG\ndef main(addition, l1=[]):\n l1.append(addition)\n return l1\nprint(main(2)) # [2]\nprint(main(3)) # [2, 3] \u2190 BUG: l1 persists!\nDefault values are part of the function HEADER (not the call). When argument is omitted, the default is used. Keyword args in a call use =. CRITICAL: mutable defaults are evaluated ONCE at def time \u2014 never use mutable defaults; use None instead." + }, + { + "item_id": "ai-example-7", + "card_id": "w3-arguments", + "topic": "Arguments", + "subtopic_id": "w3-arguments-core", + "subtopic_title": "Positional, Keyword, Default, *args, **kwargs, and Mutable Argument Traps", + "item_type": "ai_example", + "bucket": "aiExamples", + "selection_kind": "direct", + "search_text": "Function return value and trace\ndef adder(n1, n2):\n return n1 + n2\nprint(adder(1, 2))\nTrace the returned value, not just what gets printed while the function runs." + }, + { + "item_id": "ai-example-8", + "card_id": "w3-arguments", + "topic": "Arguments", + "subtopic_id": "w3-arguments-core", + "subtopic_title": "Positional, Keyword, Default, *args, **kwargs, and Mutable Argument Traps", + "item_type": "ai_example", + "bucket": "aiExamples", + "selection_kind": "direct", + "search_text": "Function return value and trace\ndef multiplier(first, second=2):\n return first * second\nprint(multiplier(3))\nTrace the returned value, not just what gets printed while the function runs." + }, + { + "item_id": "exam-intro_python_sample_final_24_25-23-w3-arguments", + "card_id": "w3-arguments", + "topic": "Arguments", + "subtopic_id": "", + "subtopic_title": "", + "item_type": "source_exam", + "bucket": "recommended", + "selection_kind": "source", + "search_text": "Which of the following function calls would return the number 30 as a result?\nA\nB\nC\nD\nC\nThe first call sums (6+7+8+9)=30. The second call sums (1+4+9+16)=30." + }, + { + "item_id": "exam-Resit 22/23-4-w3-arguments", + "card_id": "w3-arguments", + "topic": "Arguments", + "subtopic_id": "", + "subtopic_title": "", + "item_type": "source_exam", + "bucket": "recommended", + "selection_kind": "source", + "search_text": "Suppose you have the following function, which takes two integers as arguments:\nWhat will be printed by the following line of code:\nprint(main(1))\na\nb\nc\nd\na\nThe function `main` is called with `x=1`. `y` defaults to 11. The `while` loop runs while `i < 11`, which means it will run for `i` from 1 to 10 inclusive, resulting in a list of 10 formatted multiplication strings." + }, + { + "item_id": "exam-Test Resit - Introduction to Python - 22/23-6-w3-arguments", + "card_id": "w3-arguments", + "topic": "Arguments", + "subtopic_id": "", + "subtopic_title": "", + "item_type": "source_exam", + "bucket": "recommended", + "selection_kind": "source", + "search_text": "You need to write a function called main which accepts a flexible number of keyword arguments. The function should compute and return the sum of the values of the arguments.\n\nFor example, if you call the function as:\nmain(apple=1.99, banana=0.99, orange=1.49)\nit should return:\n4.47\n\nWhich of the following functions will return the intended value?\na\nb\nc\nd\nb\nOption B correctly iterates over the values of the kwargs dictionary and adds each price to the total. Option A would cause a TypeError because it tries to add a string key ('item') to an integer." + }, + { + "item_id": "exam-Resit 22/23-6-w3-arguments", + "card_id": "w3-arguments", + "topic": "Arguments", + "subtopic_id": "", + "subtopic_title": "", + "item_type": "source_exam", + "bucket": "recommended", + "selection_kind": "source", + "search_text": "You need to write a function called main which accepts a flexible number of keyword arguments. The function should compute and return the sum of the values of the arguments.\nFor example, if you call the function as:\nmain(apple=1.99, banana=0.99, orange=1.49)\nit should return:\n4.47\nWhich of the following functions will return the intended value?\na\nb\nc\nd\nb\nOption B correctly iterates through the values of the `kwargs` dictionary using `kwargs.values()` and sums them. Option A tries to add the keys (`item`), which are strings. Option C tries to unpack keys into two variables, which will fail or iterate through string characters incorrectly." + }, + { + "item_id": "exam-midterm_2023-9-w3-arguments", + "card_id": "w3-arguments", + "topic": "Arguments", + "subtopic_id": "", + "subtopic_title": "", + "item_type": "source_exam", + "bucket": "recommended", + "selection_kind": "source", + "search_text": "Suppose you have the following function:\ndef add_numbers(num1, num2 = 10, num3 = 20):\nreturn num1 + num2 + num3\nWhat are the outputs if we call the function three times as follows:\nadd_numbers(5, 15)\nadd_numbers(5, num3 = 30)\nadd_numbers(num2 = 15, num3 = 10)\nA 40\n45\n25\nB 40\n45\nThe code will result in TypeError because there is a missing argument.\nC 25\n35\n35\nD All three lines of code will result in TypeError because there is a missing argument." + }, + { + "item_id": "exam-midterm_2023-10-w3-arguments", + "card_id": "w3-arguments", + "topic": "Arguments", + "subtopic_id": "", + "subtopic_title": "", + "item_type": "source_exam", + "bucket": "recommended", + "selection_kind": "source", + "search_text": "You need to write a function called print_info which takes two required arguments called name and age, and a flexible number of keyword\narguments.\nThe function should return a dictionary with name, age, and all other key-value pairs that may be passed as keyword arguments." + }, + { + "item_id": "exam-midterm_2024-13-w3-arguments", + "card_id": "w3-arguments", + "topic": "Arguments", + "subtopic_id": "", + "subtopic_title": "", + "item_type": "source_exam", + "bucket": "recommended", + "selection_kind": "source", + "search_text": "You have to write a function called summarize which take a list of integers as an argument." + }, + { + "item_id": "exam-midterm_2024-14-w3-arguments", + "card_id": "w3-arguments", + "topic": "Arguments", + "subtopic_id": "", + "subtopic_title": "", + "item_type": "source_exam", + "bucket": "recommended", + "selection_kind": "source", + "search_text": "Suppose you have the following function:\ndef multiply(*args, factor=2):\ntotal = 1\nfor num in args:\ntotal *= num\nreturn total * factor\nWhich of the following functions will return the same values as the function above, if we call the function thrice as follows:\nmultiply(1, 2, factor=3)\nmultiply(3, 4)\nmultiply()\nA def multiply(*args, factor=2):\ntotal = args[0]\nfor num in args:\ntotal *= num\nreturn total * factor\nB def multiply(*args, factor=2):\nif not args:\nreturn 0\ntotal = args[0]\nfor num in args[1:]:\ntotal *= num\nreturn total * factor\nC Both functions will return the same values.\nD Neither functions will return the same values." + }, + { + "item_id": "ks-40fee04740", + "card_id": "w3-arguments", + "topic": "Arguments", + "subtopic_id": "", + "subtopic_title": "", + "item_type": "source_lecture", + "bucket": "recommended", + "selection_kind": "source", + "search_text": "*args \u2014 undefined number of positional arguments\nPrefixing a parameter with * makes Python collect all extra positional arguments into a tuple named args. Can mix with defined parameters: def f(n1, n2, *args) \u2014 Python fills n1,n2 first then collects remainder into args.\n*args usage\ndef adder(*args):\n result = 0\n for number in args:\n result += number\n return result\nprint(adder(1, 2, 3, 4, 5)) # 15\nMix defined and *args\ndef adder(n1, n2, *args):\n result = n1 + n2\n for number in args:\n result += number\n return result\nprint(adder(1, 2, 3, 4, 5)) # 15" + }, + { + "item_id": "ks-f5d65c7e89", + "card_id": "w3-arguments", + "topic": "Arguments", + "subtopic_id": "", + "subtopic_title": "", + "item_type": "source_lecture", + "bucket": "recommended", + "selection_kind": "source", + "search_text": "Keyword arguments and **kwargs\nArguments can be passed by name (keyword). **kwargs collects undefined keyword arguments into a dict. Order in function definition: positional, *args, keyword-with-defaults, **kwargs.\nKeyword arguments\ndef calc(first, second, third, fourth, fifth, sixth):\n return first + 2*second + 3*third + 4*fourth + 5*fifth + 6*sixth\nprint(calc(fifth=2, third=4, fourth=1, sixth=5, second=2, first=3)) # 63\n**kwargs\ndef calc(**kwargs):\n return kwargs['first'] + 2*kwargs['second'] + 3*kwargs['third']\nprint(calc(third=4, second=2, first=3))\nMixed: positional + *args + **kwargs\ndef calc(first, second, *args, **kwargs):\n return first + second*2 + args[0]*3 + args[1]*4 + 5*kwargs['fifth'] + 6*kwargs['sixth']\nprint(calc(3, 2, 4, 1, sixth=5, fifth=2)) # 63" + }, + { + "item_id": "ks-d26b85265c", + "card_id": "w3-arguments", + "topic": "Arguments", + "subtopic_id": "", + "subtopic_title": "", + "item_type": "source_lecture", + "bucket": "recommended", + "selection_kind": "source", + "search_text": "Default arguments\nDefault values are part of the function HEADER (not the call). When argument is omitted, the default is used. Keyword args in a call use =. CRITICAL: mutable defaults are evaluated ONCE at def time \u2014 never use mutable defaults; use None instead.\nDefault value\ndef multiplier(first, second=2):\n return first * second\nprint(multiplier(3)) # 6 (uses default second=2)\nprint(multiplier(3, 3)) # 9\nprint(multiplier(2, second=3)) # 6\nMutable default BUG\ndef main(addition, l1=[]):\n l1.append(addition)\n return l1\nprint(main(2)) # [2]\nprint(main(3)) # [2, 3] \u2190 BUG: l1 persists!\nMutable default FIX \u2014 use None\ndef main(addition, l1=None):\n if l1 is None:\n l1 = []\n l1 += [addition]\n return l1\nprint(main(2)) # [2]\nprint(main(3)) # [3] \u2190 correct" + }, + { + "item_id": "aiq-1", + "card_id": "w3-higher-order-patterns", + "topic": "Higher-Order Patterns", + "subtopic_id": "", + "subtopic_title": "", + "item_type": "ai_common_question", + "bucket": "aiQuestions", + "selection_kind": "direct", + "search_text": "You have four different blocks of code. Three of them return the same list, one of them returns something different.\nApply the lambda/function to one element first, then extend that same transformation to the rest of the Series or iterable.\nExam \u2022 trial_midterm \u2022 Q17\nA def squared_function(x):\nreturn x**2\nprint(squared_function([1, 2, 3]))\nB print(list(map(lambda x: x**2, [1, 2, 3])))\nC def squared_function(x):\nreturn x**2\nprint(list(map(squared_function, [1, 2, 3])))\nD squared_numbers = lambda x: x**2\nprint([squared_numbers(1), squared_numbers(2), squared_numbers(3)])" + }, + { + "item_id": "aiq-2", + "card_id": "w3-higher-order-patterns", + "topic": "Higher-Order Patterns", + "subtopic_id": "", + "subtopic_title": "", + "item_type": "ai_common_question", + "bucket": "aiQuestions", + "selection_kind": "direct", + "search_text": "You need to write a function called sort_list that accepts a list of integers.\nCheck whether the method mutates the list in place and what the list looks like after each call.\nExam \u2022 midterm_2023 \u2022 Q11\nFor example:\nIf we call the function as:\nsort_list([-9, 2, 5, -3, -10, 4, 7])\nthen it should return the list:\n[-10, -9, 7, 5, 4, -3, 2]\nWhich of the following functions will give you the correct output?" + }, + { + "item_id": "aiq-3", + "card_id": "w3-higher-order-patterns", + "topic": "Higher-Order Patterns", + "subtopic_id": "", + "subtopic_title": "", + "item_type": "ai_common_question", + "bucket": "aiQuestions", + "selection_kind": "direct", + "search_text": "Suppose you have the following functions, one to elevates a number to square and the second elevates to cube:\nApply the lambda/function to one element first, then extend that same transformation to the rest of the Series or iterable.\nExam \u2022 midterm_2023 \u2022 Q13\nSuppose you have the following functions, one to elevates a number to square and the second elevates to cube:\ndef square(n):\nreturn (n**2)\ndef cube(n):\nreturn (n**3)\nYou want to apply both functions to the elements in a list at the same time.\nFor example:\nIf you have a list such as:\nmy_list = [0, 1, 2, 3, 4]\nyou want to print:\n[0, 0]\n[1, 1]" + }, + { + "item_id": "aiq-5", + "card_id": "w3-higher-order-patterns", + "topic": "Higher-Order Patterns", + "subtopic_id": "", + "subtopic_title": "", + "item_type": "ai_common_question", + "bucket": "aiQuestions", + "selection_kind": "direct", + "search_text": "map/filter return iterables, not lists\nlist(map(lambda x: x*2, l)) \u2014 must wrap in list(). Without it: " + }, + { + "item_id": "kp-1", + "card_id": "w3-higher-order-patterns", + "topic": "Higher-Order Patterns", + "subtopic_id": "w3-higher-order-patterns-core", + "subtopic_title": "Nested Functions, Factories, lambda, map, filter, reduce, and sorted(key=...)", + "item_type": "key_point", + "bucket": "keyPoints", + "selection_kind": "direct", + "search_text": "Functions can be defined inside other functions. The inner function is only visible to the outer function. Functions are objects \u2014 a function can return another function (factory pattern)." + }, + { + "item_id": "kp-1-d1", + "card_id": "w3-higher-order-patterns", + "topic": "Higher-Order Patterns", + "subtopic_id": "", + "subtopic_title": "", + "item_type": "key_point_detail", + "bucket": "keyPoints", + "selection_kind": "detail", + "search_text": "Function factory\ndef function_factory(increment):\n def adder(n1):\n return n1 + increment\n return adder\nadd4 = function_factory(4)\nadd5 = function_factory(5)\nprint(add4(3)) # 7\nprint(add5(3)) # 8" + }, + { + "item_id": "kp-1-d2", + "card_id": "w3-higher-order-patterns", + "topic": "Higher-Order Patterns", + "subtopic_id": "", + "subtopic_title": "", + "item_type": "key_point_detail", + "bucket": "keyPoints", + "selection_kind": "detail", + "search_text": "Dense reference table\nTool | Returns | Best for\nmap(f, seq) | lazy transformed iterable | same-length transform\nfilter(f, seq) | lazy filtered iterable | keep matching items\nsorted(seq, key=...) | new sorted list | comparison key\nlambda x: ... | anonymous function | small inline transform" + }, + { + "item_id": "kp-2", + "card_id": "w3-higher-order-patterns", + "topic": "Higher-Order Patterns", + "subtopic_id": "w3-higher-order-patterns-core", + "subtopic_title": "Nested Functions, Factories, lambda, map, filter, reduce, and sorted(key=...)", + "item_type": "key_point", + "bucket": "keyPoints", + "selection_kind": "direct", + "search_text": "Anonymous one-line functions. Syntax: lambda params: expression. Equivalent to a regular def but more concise. Most useful with map, filter, reduce, sorted, max." + }, + { + "item_id": "kp-2-d1", + "card_id": "w3-higher-order-patterns", + "topic": "Higher-Order Patterns", + "subtopic_id": "", + "subtopic_title": "", + "item_type": "key_point_detail", + "bucket": "keyPoints", + "selection_kind": "detail", + "search_text": "Lambda basics\nadd_two = lambda x, y: x + y\nprint(add_two(1, 2)) # 3\n# Equivalent to:\ndef add_two(x, y):\n return x + y" + }, + { + "item_id": "kp-2-d2", + "card_id": "w3-higher-order-patterns", + "topic": "Higher-Order Patterns", + "subtopic_id": "", + "subtopic_title": "", + "item_type": "key_point_detail", + "bucket": "keyPoints", + "selection_kind": "detail", + "search_text": "map() with lambda\nl1 = [1, 2, 3, 4, 5, 6]\nprint(list(map(lambda x: x * 2, l1))) # [2, 4, 6, 8, 10, 12]\n# Need list() to convert map object to list" + }, + { + "item_id": "kp-3", + "card_id": "w3-higher-order-patterns", + "topic": "Higher-Order Patterns", + "subtopic_id": "w3-higher-order-patterns-core", + "subtopic_title": "Nested Functions, Factories, lambda, map, filter, reduce, and sorted(key=...)", + "item_type": "key_point", + "bucket": "keyPoints", + "selection_kind": "direct", + "search_text": "def function_factory(increment): def adder(n1): return n1 + increment return adder add4 = function_factory(4) add5 = function_factory (5) print(add4(3)) print(add5(3))" + }, + { + "item_id": "ai-example-1", + "card_id": "w3-higher-order-patterns", + "topic": "Higher-Order Patterns", + "subtopic_id": "w3-higher-order-patterns-core", + "subtopic_title": "Nested Functions, Factories, lambda, map, filter, reduce, and sorted(key=...)", + "item_type": "ai_example", + "bucket": "aiExamples", + "selection_kind": "direct", + "search_text": "Function factory\ndef function_factory(increment):\n def adder(n1):\n return n1 + increment\n return adder\nadd4 = function_factory(4)\nadd5 = function_factory(5)\nprint(add4(3)) # 7\nprint(add5(3)) # 8\nFunctions can be defined inside other functions. The inner function is only visible to the outer function. Functions are objects \u2014 a function can return another function (factory pattern)." + }, + { + "item_id": "ai-example-2", + "card_id": "w3-higher-order-patterns", + "topic": "Higher-Order Patterns", + "subtopic_id": "w3-higher-order-patterns-core", + "subtopic_title": "Nested Functions, Factories, lambda, map, filter, reduce, and sorted(key=...)", + "item_type": "ai_example", + "bucket": "aiExamples", + "selection_kind": "direct", + "search_text": "Lambda basics\nadd_two = lambda x, y: x + y\nprint(add_two(1, 2)) # 3\n# Equivalent to:\ndef add_two(x, y):\n return x + y\nAnonymous one-line functions. Syntax: lambda params: expression. Equivalent to a regular def but more concise. Most useful with map, filter, reduce, sorted, max." + }, + { + "item_id": "ai-example-3", + "card_id": "w3-higher-order-patterns", + "topic": "Higher-Order Patterns", + "subtopic_id": "w3-higher-order-patterns-core", + "subtopic_title": "Nested Functions, Factories, lambda, map, filter, reduce, and sorted(key=...)", + "item_type": "ai_example", + "bucket": "aiExamples", + "selection_kind": "direct", + "search_text": "map() with lambda\nl1 = [1, 2, 3, 4, 5, 6]\nprint(list(map(lambda x: x * 2, l1))) # [2, 4, 6, 8, 10, 12]\n# Need list() to convert map object to list\nAnonymous one-line functions. Syntax: lambda params: expression. Equivalent to a regular def but more concise. Most useful with map, filter, reduce, sorted, max." + }, + { + "item_id": "ai-example-4", + "card_id": "w3-higher-order-patterns", + "topic": "Higher-Order Patterns", + "subtopic_id": "w3-higher-order-patterns-core", + "subtopic_title": "Nested Functions, Factories, lambda, map, filter, reduce, and sorted(key=...)", + "item_type": "ai_example", + "bucket": "aiExamples", + "selection_kind": "direct", + "search_text": "Elementwise transformation with `map`/`lambda`\nprint((lambda x, y: 2*x*y)(4, 3))\nApply the lambda/function to one element first, then extend that same transformation to the rest of the Series or iterable." + }, + { + "item_id": "ai-example-5", + "card_id": "w3-higher-order-patterns", + "topic": "Higher-Order Patterns", + "subtopic_id": "w3-higher-order-patterns-core", + "subtopic_title": "Nested Functions, Factories, lambda, map, filter, reduce, and sorted(key=...)", + "item_type": "ai_example", + "bucket": "aiExamples", + "selection_kind": "direct", + "search_text": "sorted_key\nl1 = ['a', 'B', 'c']\nprint(sorted(l1))" + }, + { + "item_id": "ai-example-6", + "card_id": "w3-higher-order-patterns", + "topic": "Higher-Order Patterns", + "subtopic_id": "w3-higher-order-patterns-core", + "subtopic_title": "Nested Functions, Factories, lambda, map, filter, reduce, and sorted(key=...)", + "item_type": "ai_example", + "bucket": "aiExamples", + "selection_kind": "direct", + "search_text": "sorted_key\nl1 = ['ad', 'dc', 'ce']\nprint(sorted(l1))" + }, + { + "item_id": "ai-example-7", + "card_id": "w3-higher-order-patterns", + "topic": "Higher-Order Patterns", + "subtopic_id": "w3-higher-order-patterns-core", + "subtopic_title": "Nested Functions, Factories, lambda, map, filter, reduce, and sorted(key=...)", + "item_type": "ai_example", + "bucket": "aiExamples", + "selection_kind": "direct", + "search_text": "sorted_builtins\nl1 = ['aaa', 'bb', 'c']\nprint(sorted(l1))" + }, + { + "item_id": "ai-example-8", + "card_id": "w3-higher-order-patterns", + "topic": "Higher-Order Patterns", + "subtopic_id": "w3-higher-order-patterns-core", + "subtopic_title": "Nested Functions, Factories, lambda, map, filter, reduce, and sorted(key=...)", + "item_type": "ai_example", + "bucket": "aiExamples", + "selection_kind": "direct", + "search_text": "sorted_builtins\nl1 = ['aaa', 'bb', 'c']\nprint(sorted(l1, key=len))" + }, + { + "item_id": "exam-intro_python_sample_final_24_25-16-w3-higher-order-patterns", + "card_id": "w3-higher-order-patterns", + "topic": "Higher-Order Patterns", + "subtopic_id": "", + "subtopic_title": "", + "item_type": "source_exam", + "bucket": "recommended", + "selection_kind": "source", + "search_text": "What would be printed by the following code snippet: print(list_1[0](1, 2) ** list_1[1](1, 2))\nA\nB\nC\nD\nD\nlist_1[0](1, 2) is 1 + 2 = 3. list_1[1](1, 2) is 1 * 2 = 2. 3 ** 2 = 9." + }, + { + "item_id": "exam-midterm_2023-11-w3-higher-order-patterns", + "card_id": "w3-higher-order-patterns", + "topic": "Higher-Order Patterns", + "subtopic_id": "", + "subtopic_title": "", + "item_type": "source_exam", + "bucket": "recommended", + "selection_kind": "source", + "search_text": "You need to write a function called sort_list that accepts a list of integers.\nThe function should return a new list, in which the elements are sorted from highest to lowest based on their absolute values." + }, + { + "item_id": "exam-midterm_2023-13-w3-higher-order-patterns", + "card_id": "w3-higher-order-patterns", + "topic": "Higher-Order Patterns", + "subtopic_id": "", + "subtopic_title": "", + "item_type": "source_exam", + "bucket": "recommended", + "selection_kind": "source", + "search_text": "Suppose you have the following functions, one to elevates a number to square and the second elevates to cube:\ndef square(n):\nreturn (n**2)\ndef cube(n):\nreturn (n**3)\nYou want to apply both functions to the elements in a list at the same time.\nFor example:\nIf you have a list such as:\nmy_list = [0, 1, 2, 3, 4]\nyou want to print:\n[0, 0]\n[1, 1]\n[4, 8]\n[9, 27]\n[16, 64]\nWhich of the following blocks of codes works as intended?\nA funcs = [square, cube]\nfor i in my_list:\nresults = map(lambda x: x(i), funcs)\nprint(list(results))\nB funcs = [square, cube]\nfor i in my_list:\nresults = map(lambda x: x[i], funcs)\nprint(list(results))\nC funcs = [square, cube]\nfor i in my_list:\nresults = map(lambda x: x(i), funcs)\nprint(results)\nD funcs = [square, cube]\nfor i in my_list:\nresults = map(lambda x: x[i], funcs)\nprint(results)" + }, + { + "item_id": "exam-trial_midterm-17-w3-higher-order-patterns", + "card_id": "w3-higher-order-patterns", + "topic": "Higher-Order Patterns", + "subtopic_id": "", + "subtopic_title": "", + "item_type": "source_exam", + "bucket": "recommended", + "selection_kind": "source", + "search_text": "You have four different blocks of code. Three of them return the same list, one of them returns something different.\nWhich block of code prints something different than the other blocks print?" + }, + { + "item_id": "exam-midterm_2024-19-w3-higher-order-patterns", + "card_id": "w3-higher-order-patterns", + "topic": "Higher-Order Patterns", + "subtopic_id": "", + "subtopic_title": "", + "item_type": "source_exam", + "bucket": "recommended", + "selection_kind": "source", + "search_text": "You have four different blocks of code. Three of them return the same list, one of them returns something different.\nWhich block of code prints something different than the other blocks print?" + }, + { + "item_id": "ks-f069ee6a0b", + "card_id": "w3-higher-order-patterns", + "topic": "Higher-Order Patterns", + "subtopic_id": "", + "subtopic_title": "", + "item_type": "source_lecture", + "bucket": "recommended", + "selection_kind": "source", + "search_text": "Nested functions and function factories\nFunctions can be defined inside other functions. The inner function is only visible to the outer function. Functions are objects \u2014 a function can return another function (factory pattern).\nFunction factory\ndef function_factory(increment):\n def adder(n1):\n return n1 + increment\n return adder\nadd4 = function_factory(4)\nadd5 = function_factory(5)\nprint(add4(3)) # 7\nprint(add5(3)) # 8" + }, + { + "item_id": "ks-58858d6d96", + "card_id": "w3-higher-order-patterns", + "topic": "Higher-Order Patterns", + "subtopic_id": "", + "subtopic_title": "", + "item_type": "source_lecture", + "bucket": "recommended", + "selection_kind": "source", + "search_text": "Lambda functions\nAnonymous one-line functions. Syntax: lambda params: expression. Equivalent to a regular def but more concise. Most useful with map, filter, reduce, sorted, max.\nLambda basics\nadd_two = lambda x, y: x + y\nprint(add_two(1, 2)) # 3\n# Equivalent to:\ndef add_two(x, y):\n return x + y\nmap() with lambda\nl1 = [1, 2, 3, 4, 5, 6]\nprint(list(map(lambda x: x * 2, l1))) # [2, 4, 6, 8, 10, 12]\n# Need list() to convert map object to list\nfilter() with lambda\nl1 = [1, 2, 3, 4, 5, 6]\nprint(list(filter(lambda x: not x % 2, l1))) # [2, 4, 6] (even numbers)\nreduce() with lambda\nfrom functools import reduce\nl1 = [1, 2, 3, 4, 5, 6]\nprint(reduce(lambda x, y: x*y, l1)) # 720 (product)\n# reduce with initial value:\nl1 = ['aaa', 'baab', 'c']\nprint(reduce(lambda x, y: x + y.count('a'), l1, 0)) # 5\nsorted() with key lambda\nl1 = ['aaa', 'c', 'baab']\nprint(sorted(l1)) # ['aaa', 'baab', 'c']\nprint(sorted(l1, key=lambda x: x.count('a'))) # ['c', 'baab', 'aaa']\nprint(sorted(l1, key=len)) # ['c', 'aaa', 'baab']\n\nd = {'a': 2, 'b': 1}\nprint(max(d.items())) # ('b', 1) \u2190 compares tuples\nprint(max(d.items(), key=lambda x: x[1])) # ('a', 2) \u2190 by value" + }, + { + "item_id": "ks-994a4083e3", + "card_id": "w3-higher-order-patterns", + "topic": "Higher-Order Patterns", + "subtopic_id": "", + "subtopic_title": "", + "item_type": "source_lecture", + "bucket": "recommended", + "selection_kind": "source", + "search_text": "function_factories\ndef function_factory(increment):\n def adder(n1):\n return n1 + increment\n return adder\n\nadd4 = function_factory(4)\nadd5 = function_factory (5)\n\nprint(add4(3))\nprint(add5(3))" + }, + { + "item_id": "exam-extra_practice-10-w3-higher-order-patterns", + "card_id": "w3-higher-order-patterns", + "topic": "Higher-Order Patterns", + "subtopic_id": "", + "subtopic_title": "", + "item_type": "source_exam", + "bucket": "additional", + "selection_kind": "source", + "search_text": "You need to write a function main(target_num, list_num) that returns all unique pairs of numbers that add up to target_num.\n\nExample: main(11, [4,5,6,9,3,7,2,8]) should return [(5,6),(4,7),(9,2),(3,8)].\n\nNote: (6,5) is not included since (5,6) is already found.\n\nWhich of the following code snippets achieve what you want?\na\nb\nc\nd\nb\nOption a produces both (5,6) and (6,5) \u2014 it doesn't ensure uniqueness. Option b iterates up to target//2, so each pair is only considered once. For target=11, range(0,6): checks 0,1,2,3,4,5. Finds: 2+9,3+8,4+7,5+6 \u2014 unique pairs. Option b works as intended. Option a doesn't meet the uniqueness requirement. Correct: b." + }, + { + "item_id": "aiq-1", + "card_id": "w4-string-fundamentals", + "topic": "String Fundamentals", + "subtopic_id": "", + "subtopic_title": "", + "item_type": "ai_common_question", + "bucket": "aiQuestions", + "selection_kind": "direct", + "search_text": "Given s1 = 'abcd', which code fragment correctly updates s1 to 'Abcd'?\nStrings are immutable. s1.capitalize() returns a new string, so you must assign that result back to the name s1.\nString Methods" + }, + { + "item_id": "manual-string-immutability", + "card_id": "w4-string-fundamentals", + "topic": "String Fundamentals", + "subtopic_id": "", + "subtopic_title": "", + "item_type": "ai_common_question", + "bucket": "aiQuestions", + "selection_kind": "direct", + "search_text": "Why does `s[0] = 'A'` fail?\nStrings are immutable, so you must build a new string such as `s = 'A' + s[1:]` instead of assigning by index.\ns = 'abcd'\ns = 'A' + s[1:]" + }, + { + "item_id": "manual-string-escapes", + "card_id": "w4-string-fundamentals", + "topic": "String Fundamentals", + "subtopic_id": "", + "subtopic_title": "", + "item_type": "ai_common_question", + "bucket": "aiQuestions", + "selection_kind": "direct", + "search_text": "How do you include quotes or a newline inside a string literal?\nPick the other quote style or escape the inner quote; use `\\n` for a newline.\nprint(\"it's\")\nprint('He said \"hi\"')\nprint(\"Line 1\\nLine 2\")" + }, + { + "item_id": "kp-1", + "card_id": "w4-string-fundamentals", + "topic": "String Fundamentals", + "subtopic_id": "w4-string-fundamentals-core", + "subtopic_title": "Quotes, Escape Characters, and Immutability", + "item_type": "key_point", + "bucket": "keyPoints", + "selection_kind": "direct", + "search_text": "Strings are immutable: methods like `.upper()` and `.replace()` return a new string, so assign the result back if you want the change to stick." + }, + { + "item_id": "kp-1-d1", + "card_id": "w4-string-fundamentals", + "topic": "String Fundamentals", + "subtopic_id": "", + "subtopic_title": "", + "item_type": "key_point_detail", + "bucket": "keyPoints", + "selection_kind": "detail", + "search_text": "Attempting to change a string\ns1 = 'abcd'\ns1.capitalize() # Returns 'Abcd'\nprint(s1) # Still prints 'abcd'" + }, + { + "item_id": "kp-1-d2", + "card_id": "w4-string-fundamentals", + "topic": "String Fundamentals", + "subtopic_id": "", + "subtopic_title": "", + "item_type": "key_point_detail", + "bucket": "keyPoints", + "selection_kind": "detail", + "search_text": "Dense reference table\nForm | What it means | Exam use\n'...'/\"...\" | basic literals | choose quote style\n\\n / \\t | newline / tab | predict printed output\nr'...' | raw string | slashes stay literal\ns[i:j:k] | string slicing | same rules as sequences" + }, + { + "item_id": "kp-2", + "card_id": "w4-string-fundamentals", + "topic": "String Fundamentals", + "subtopic_id": "w4-string-fundamentals-core", + "subtopic_title": "Quotes, Escape Characters, and Immutability", + "item_type": "key_point", + "bucket": "keyPoints", + "selection_kind": "direct", + "search_text": "Escape sequences: `\\n` newline, `\\t` tab, and `\\'` or `\\\"` for literal quotes." + }, + { + "item_id": "kp-2-d1", + "card_id": "w4-string-fundamentals", + "topic": "String Fundamentals", + "subtopic_id": "", + "subtopic_title": "", + "item_type": "key_point_detail", + "bucket": "keyPoints", + "selection_kind": "detail", + "search_text": "Newlines and tabs\nprint('Line 1\\nLine 2\\tTabbed')\nprint(\"It\\'s a string\")" + }, + { + "item_id": "kp-3", + "card_id": "w4-string-fundamentals", + "topic": "String Fundamentals", + "subtopic_id": "w4-string-fundamentals-core", + "subtopic_title": "Quotes, Escape Characters, and Immutability", + "item_type": "key_point", + "bucket": "keyPoints", + "selection_kind": "direct", + "search_text": "Strings are immutable: `s[0] = 'A'` fails, so rebuild or rebind, for example `s = 'A' + s[1:]`." + }, + { + "item_id": "ai-example-1", + "card_id": "w4-string-fundamentals", + "topic": "String Fundamentals", + "subtopic_id": "w4-string-fundamentals-core", + "subtopic_title": "Quotes, Escape Characters, and Immutability", + "item_type": "ai_example", + "bucket": "aiExamples", + "selection_kind": "direct", + "search_text": "Methods return new strings\ns1 = 'abcd'\ns1.capitalize() # Returns 'Abcd'\nprint(s1) # Still prints 'abcd'\nStrings are immutable: methods like `.upper()` and `.replace()` return a new string, so assign the result back if you want the change to stick.\nabcd" + }, + { + "item_id": "ai-example-2", + "card_id": "w4-string-fundamentals", + "topic": "String Fundamentals", + "subtopic_id": "w4-string-fundamentals-core", + "subtopic_title": "Quotes, Escape Characters, and Immutability", + "item_type": "ai_example", + "bucket": "aiExamples", + "selection_kind": "direct", + "search_text": "Newlines and tabs\nprint('Line 1\\nLine 2\\tTabbed')\nprint(\"It\\'s a string\")\nEscape sequences: `\\n` newline, `\\t` tab, and `\\'` or `\\\"` for literal quotes." + }, + { + "item_id": "ai-example-4", + "card_id": "w4-string-fundamentals", + "topic": "String Fundamentals", + "subtopic_id": "w4-string-fundamentals-core", + "subtopic_title": "Quotes, Escape Characters, and Immutability", + "item_type": "ai_example", + "bucket": "aiExamples", + "selection_kind": "direct", + "search_text": "Filter uppercase letters with a helper function\ndef my_isupper(s1):\n for el in s1:\n if el not in \"ABCDEFGHIJKLMNOPQRSTUVWXYZ\":\n return False\n return True \n\nx = \"Harry Potter and the Philosopher's Stone\"\ny = ''\nfor i in x:\n if my_isupper(i):\n y += i\nprint(y)\nTrace the loop character by character and keep only the uppercase letters that satisfy the test.\nHPPS" + }, + { + "item_id": "ai-example-8", + "card_id": "w4-string-fundamentals", + "topic": "String Fundamentals", + "subtopic_id": "w4-string-fundamentals-core", + "subtopic_title": "Quotes, Escape Characters, and Immutability", + "item_type": "ai_example", + "bucket": "aiExamples", + "selection_kind": "direct", + "search_text": "`len(s)` counts characters\na = 'adbc'\nprint(len(a))\nCount every character in the string, including letters, spaces, and punctuation if they are present.\n4" + }, + { + "item_id": "manual-string-literals-example", + "card_id": "w4-string-fundamentals", + "topic": "String Fundamentals", + "subtopic_id": "w4-string-fundamentals-core", + "subtopic_title": "Quotes, Escape Characters, and Immutability", + "item_type": "ai_example", + "bucket": "aiExamples", + "selection_kind": "direct", + "search_text": "Quotes and newline escapes\nprint(\"it's\")\nprint('He said \"hi\"')\nprint(\"Line 1\\nLine 2\")\nUse matching quotes or escape the inner quote; `\\n` inserts a newline.\nit's\nHe said \"hi\"\nLine 1\nLine 2" + }, + { + "item_id": "ks-b734a22f46", + "card_id": "w4-string-fundamentals", + "topic": "String Fundamentals", + "subtopic_id": "", + "subtopic_title": "", + "item_type": "source_lecture", + "bucket": "recommended", + "selection_kind": "source", + "search_text": "String Immutability\nStrings in Python are immutable, meaning they cannot be changed in place. Methods like upper() or replace() return a new string object rather than modifying the original.\nAttempting to change a string\ns1 = 'abcd'\ns1.capitalize() # Returns 'Abcd'\nprint(s1) # Still prints 'abcd'" + }, + { + "item_id": "ks-309158a68c", + "card_id": "w4-string-fundamentals", + "topic": "String Fundamentals", + "subtopic_id": "", + "subtopic_title": "", + "item_type": "source_lecture", + "bucket": "recommended", + "selection_kind": "source", + "search_text": "Escape Characters\nSpecial characters like newlines (\\n), tabs (\\t), or literal quotes can be included using the backslash (\\).\nNewlines and tabs\nprint('Line 1\\nLine 2\\tTabbed')\nprint(\"It\\'s a string\")" + }, + { + "item_id": "cs-e7bc165499", + "card_id": "w4-string-fundamentals", + "topic": "String Fundamentals", + "subtopic_id": "", + "subtopic_title": "", + "item_type": "source_notebook", + "bucket": "recommended", + "selection_kind": "source", + "search_text": "def main(a, b):\ndef main(a, b):\n return f'''The first number is: {a:04d}\nThe second number is: {b:04d}\nThe product is: {a * b:04d}'''\nprint(main(7,13))\nThe first number is: 0007\nThe second number is: 0013\nThe product is: 0091" + }, + { + "item_id": "cs-14245b8c1f", + "card_id": "w4-string-fundamentals", + "topic": "String Fundamentals", + "subtopic_id": "", + "subtopic_title": "", + "item_type": "source_notebook", + "bucket": "recommended", + "selection_kind": "source", + "search_text": "def my_isupper(s1):\ndef my_isupper(s1):\n for el in s1:\n if el not in \"ABCDEFGHIJKLMNOPQRSTUVWXYZ\":\n return False\n return True \n\nx = \"Harry Potter and the Philosopher's Stone\"\ny = ''\nfor i in x:\n if my_isupper(i):\n y += i\nprint(y)\nHPPS" + }, + { + "item_id": "aiq-2", + "card_id": "w4-string-operations-and-methods", + "topic": "String Operations and Methods", + "subtopic_id": "", + "subtopic_title": "", + "item_type": "ai_common_question", + "bucket": "aiQuestions", + "selection_kind": "direct", + "search_text": "What does the slice s[::-2] do for the string s = 'abcdef'?\nThe step -2 reverses the string and skips every second character, starting from the end ('f', then 'd', then 'b').\nString Slicing" + }, + { + "item_id": "aiq-5", + "card_id": "w4-string-operations-and-methods", + "topic": "String Operations and Methods", + "subtopic_id": "", + "subtopic_title": "", + "item_type": "ai_common_question", + "bucket": "aiQuestions", + "selection_kind": "direct", + "search_text": "Slicing creates a NEW object\nl2=l1 vs l2=l1[:] \u2014 l2=l1 shares the SAME object, slicing creates independent copy" + }, + { + "item_id": "aiq-6", + "card_id": "w4-string-operations-and-methods", + "topic": "String Operations and Methods", + "subtopic_id": "", + "subtopic_title": "", + "item_type": "ai_common_question", + "bucket": "aiQuestions", + "selection_kind": "direct", + "search_text": "range() and slicing both exclusive at stop\nrange(1,10,3)\u2192[1,4,7] not including 10; l[2:7] goes up to but not including index 7" + }, + { + "item_id": "manual-find-vs-index", + "card_id": "w4-string-operations-and-methods", + "topic": "String Operations and Methods", + "subtopic_id": "", + "subtopic_title": "", + "item_type": "ai_common_question", + "bucket": "aiQuestions", + "selection_kind": "direct", + "search_text": "What is the difference between `s.find(x)` and `s.index(x)` when `x` is missing?\n`find` returns `-1`; `index` raises `ValueError`.\ns = 'banana'\nprint(s.find('x'))\nprint(s.index('x')) # ValueError" + }, + { + "item_id": "kp-1", + "card_id": "w4-string-operations-and-methods", + "topic": "String Operations and Methods", + "subtopic_id": "w4-string-operations-and-methods-core", + "subtopic_title": "Slicing with Step, Search, replace, join, strip, and the string Module", + "item_type": "key_point", + "bucket": "keyPoints", + "selection_kind": "direct", + "search_text": "Both find() and index() search for a substring. The key difference is that find() returns -1 if the substring is not found, while index() raises a ValueError." + }, + { + "item_id": "kp-1-d1", + "card_id": "w4-string-operations-and-methods", + "topic": "String Operations and Methods", + "subtopic_id": "", + "subtopic_title": "", + "item_type": "key_point_detail", + "bucket": "keyPoints", + "selection_kind": "detail", + "search_text": "Behavior when substring is missing\ns = 'abc'\nprint(s.find('z')) # -1\n# print(s.index('z')) # Raises ValueError" + }, + { + "item_id": "kp-1-d2", + "card_id": "w4-string-operations-and-methods", + "topic": "String Operations and Methods", + "subtopic_id": "", + "subtopic_title": "", + "item_type": "key_point_detail", + "bucket": "keyPoints", + "selection_kind": "detail", + "search_text": "Dense reference table\nMethod | Returns | Trap\ns.find(x) | index or -1 | never raises\ns.index(x) | index | raises if missing\ns.replace(a, b) | new string | strings are immutable\nsep.join(seq) | new joined string | separator is the caller" + }, + { + "item_id": "kp-2", + "card_id": "w4-string-operations-and-methods", + "topic": "String Operations and Methods", + "subtopic_id": "w4-string-operations-and-methods-core", + "subtopic_title": "Slicing with Step, Search, replace, join, strip, and the string Module", + "item_type": "key_point", + "bucket": "keyPoints", + "selection_kind": "direct", + "search_text": "Slicing allows a third parameter 'step'. s[::2] takes every second character, while s[::-1] reverses the string." + }, + { + "item_id": "kp-2-d1", + "card_id": "w4-string-operations-and-methods", + "topic": "String Operations and Methods", + "subtopic_id": "", + "subtopic_title": "", + "item_type": "key_point_detail", + "bucket": "keyPoints", + "selection_kind": "detail", + "search_text": "Slicing examples\ns = '01234567'\nprint(s[::4]) # '04'\nprint(s[::-2]) # '7531'" + }, + { + "item_id": "kp-3", + "card_id": "w4-string-operations-and-methods", + "topic": "String Operations and Methods", + "subtopic_id": "w4-string-operations-and-methods-core", + "subtopic_title": "Slicing with Step, Search, replace, join, strip, and the string Module", + "item_type": "key_point", + "bucket": "keyPoints", + "selection_kind": "direct", + "search_text": "The join() method takes an iterable (like a list) and concatenates its elements using the string it is called on as a separator." + }, + { + "item_id": "kp-3-d1", + "card_id": "w4-string-operations-and-methods", + "topic": "String Operations and Methods", + "subtopic_id": "", + "subtopic_title": "", + "item_type": "key_point_detail", + "bucket": "keyPoints", + "selection_kind": "detail", + "search_text": "Joining a list into a string\nwords = ['a', 'b', 'c']\nprint('-'.join(words)) # 'a-b-c'\nprint(''.join(words)) # 'abc'" + }, + { + "item_id": "kp-4", + "card_id": "w4-string-operations-and-methods", + "topic": "String Operations and Methods", + "subtopic_id": "w4-string-operations-and-methods-core", + "subtopic_title": "Slicing with Step, Search, replace, join, strip, and the string Module", + "item_type": "key_point", + "bucket": "keyPoints", + "selection_kind": "direct", + "search_text": "Replaces occurrences of a substring. It accepts an optional 'count' argument to limit the number of replacements." + }, + { + "item_id": "kp-4-d1", + "card_id": "w4-string-operations-and-methods", + "topic": "String Operations and Methods", + "subtopic_id": "", + "subtopic_title": "", + "item_type": "key_point_detail", + "bucket": "keyPoints", + "selection_kind": "detail", + "search_text": "Limiting replacements\ns = 'aaaa'\nprint(s.replace('a', 'b', 2)) # 'bbaa'" + }, + { + "item_id": "kp-5", + "card_id": "w4-string-operations-and-methods", + "topic": "String Operations and Methods", + "subtopic_id": "w4-string-operations-and-methods-core", + "subtopic_title": "Slicing with Step, Search, replace, join, strip, and the string Module", + "item_type": "key_point", + "bucket": "keyPoints", + "selection_kind": "direct", + "search_text": "The 'string' module provides pre-defined constants like all lowercase letters, digits, and punctuation." + }, + { + "item_id": "kp-5-d1", + "card_id": "w4-string-operations-and-methods", + "topic": "String Operations and Methods", + "subtopic_id": "", + "subtopic_title": "", + "item_type": "key_point_detail", + "bucket": "keyPoints", + "selection_kind": "detail", + "search_text": "Importing string constants\nimport string\nprint(string.ascii_lowercase) # 'abcdef...'\nprint(string.digits) # '0123456789'" + }, + { + "item_id": "kp-6", + "card_id": "w4-string-operations-and-methods", + "topic": "String Operations and Methods", + "subtopic_id": "w4-string-operations-and-methods-core", + "subtopic_title": "Slicing with Step, Search, replace, join, strip, and the string Module", + "item_type": "key_point", + "bucket": "keyPoints", + "selection_kind": "direct", + "search_text": "strip() removes leading and trailing characters. lstrip() and rstrip() target the left and right sides respectively." + }, + { + "item_id": "kp-6-d1", + "card_id": "w4-string-operations-and-methods", + "topic": "String Operations and Methods", + "subtopic_id": "", + "subtopic_title": "", + "item_type": "key_point_detail", + "bucket": "keyPoints", + "selection_kind": "detail", + "search_text": "Stripping whitespace and characters\ns = ' abc '\nprint(s.strip()) # 'abc'\ns2 = 'eeabcdee'\nprint(s2.strip('e')) # 'abcd'" + }, + { + "item_id": "kp-7", + "card_id": "w4-string-operations-and-methods", + "topic": "String Operations and Methods", + "subtopic_id": "w4-string-operations-and-methods-core", + "subtopic_title": "Slicing with Step, Search, replace, join, strip, and the string Module", + "item_type": "key_point", + "bucket": "keyPoints", + "selection_kind": "direct", + "search_text": "Pattern to remember: `find` returns `-1`; `index` raises `ValueError` if the substring is missing." + }, + { + "item_id": "ai-example-1", + "card_id": "w4-string-operations-and-methods", + "topic": "String Operations and Methods", + "subtopic_id": "w4-string-operations-and-methods-core", + "subtopic_title": "Slicing with Step, Search, replace, join, strip, and the string Module", + "item_type": "ai_example", + "bucket": "aiExamples", + "selection_kind": "direct", + "search_text": "Behavior when substring is missing\ns = 'abc'\nprint(s.find('z')) # -1\n# print(s.index('z')) # Raises ValueError\nBoth find() and index() search for a substring. The key difference is that find() returns -1 if the substring is not found, while index() raises a ValueError." + }, + { + "item_id": "ai-example-2", + "card_id": "w4-string-operations-and-methods", + "topic": "String Operations and Methods", + "subtopic_id": "w4-string-operations-and-methods-core", + "subtopic_title": "Slicing with Step, Search, replace, join, strip, and the string Module", + "item_type": "ai_example", + "bucket": "aiExamples", + "selection_kind": "direct", + "search_text": "Slicing examples\ns = '01234567'\nprint(s[::4]) # '04'\nprint(s[::-2]) # '7531'\nSlicing allows a third parameter 'step'. s[::2] takes every second character, while s[::-1] reverses the string." + }, + { + "item_id": "ai-example-3", + "card_id": "w4-string-operations-and-methods", + "topic": "String Operations and Methods", + "subtopic_id": "w4-string-operations-and-methods-core", + "subtopic_title": "Slicing with Step, Search, replace, join, strip, and the string Module", + "item_type": "ai_example", + "bucket": "aiExamples", + "selection_kind": "direct", + "search_text": "Joining a list into a string\nwords = ['a', 'b', 'c']\nprint('-'.join(words)) # 'a-b-c'\nprint(''.join(words)) # 'abc'\nThe join() method takes an iterable (like a list) and concatenates its elements using the string it is called on as a separator." + }, + { + "item_id": "ai-example-4", + "card_id": "w4-string-operations-and-methods", + "topic": "String Operations and Methods", + "subtopic_id": "w4-string-operations-and-methods-core", + "subtopic_title": "Slicing with Step, Search, replace, join, strip, and the string Module", + "item_type": "ai_example", + "bucket": "aiExamples", + "selection_kind": "direct", + "search_text": "Limiting replacements\ns = 'aaaa'\nprint(s.replace('a', 'b', 2)) # 'bbaa'\nReplaces occurrences of a substring. It accepts an optional 'count' argument to limit the number of replacements." + }, + { + "item_id": "ai-example-5", + "card_id": "w4-string-operations-and-methods", + "topic": "String Operations and Methods", + "subtopic_id": "w4-string-operations-and-methods-core", + "subtopic_title": "Slicing with Step, Search, replace, join, strip, and the string Module", + "item_type": "ai_example", + "bucket": "aiExamples", + "selection_kind": "direct", + "search_text": "Importing string constants\nimport string\nprint(string.ascii_lowercase) # 'abcdef...'\nprint(string.digits) # '0123456789'\nThe 'string' module provides pre-defined constants like all lowercase letters, digits, and punctuation." + }, + { + "item_id": "ai-example-6", + "card_id": "w4-string-operations-and-methods", + "topic": "String Operations and Methods", + "subtopic_id": "w4-string-operations-and-methods-core", + "subtopic_title": "Slicing with Step, Search, replace, join, strip, and the string Module", + "item_type": "ai_example", + "bucket": "aiExamples", + "selection_kind": "direct", + "search_text": "Stripping whitespace and characters\ns = ' abc '\nprint(s.strip()) # 'abc'\ns2 = 'eeabcdee'\nprint(s2.strip('e')) # 'abcd'\nstrip() removes leading and trailing characters. lstrip() and rstrip() target the left and right sides respectively." + }, + { + "item_id": "ai-example-7", + "card_id": "w4-string-operations-and-methods", + "topic": "String Operations and Methods", + "subtopic_id": "w4-string-operations-and-methods-core", + "subtopic_title": "Slicing with Step, Search, replace, join, strip, and the string Module", + "item_type": "ai_example", + "bucket": "aiExamples", + "selection_kind": "direct", + "search_text": "s1 = 'abcdefghabcdefgh'\ns1 = 'abcdefghabcdefgh'\nprint(s1.find('i'))\nprint(s1[s1.find('i')])\nprint(s1.index('i'))" + }, + { + "item_id": "ai-example-8", + "card_id": "w4-string-operations-and-methods", + "topic": "String Operations and Methods", + "subtopic_id": "w4-string-operations-and-methods-core", + "subtopic_title": "Slicing with Step, Search, replace, join, strip, and the string Module", + "item_type": "ai_example", + "bucket": "aiExamples", + "selection_kind": "direct", + "search_text": "s1 = 'abcdefghabcdefgh'\ns1 = 'abcdefghabcdefgh'\nprint(s1.find('e'))\nprint(s1.index('e', 5))\nprint(s1.find('e', 5, 10))\nprint(s1.index('e', 5, 13))\nprint(s1.find('ef'))\nprint(s1.index('q'))" + }, + { + "item_id": "manual-string-format-method", + "card_id": "w4-string-operations-and-methods", + "topic": "String Operations and Methods", + "subtopic_id": "w4-string-operations-and-methods-core", + "subtopic_title": "Slicing with Step, Search, replace, join, strip, and the string Module", + "item_type": "ai_example", + "bucket": "aiExamples", + "selection_kind": "direct", + "search_text": "Build strings with `.format(...)`\ntemplate = \"{} scored {} points\"\nprint(template.format(\"Ada\", 9))\nUse `.format(...)` on the template string, and remember it returns a new string instead of changing the original text in place.\nAda scored 9 points" + }, + { + "item_id": "manual-string-islower-method", + "card_id": "w4-string-operations-and-methods", + "topic": "String Operations and Methods", + "subtopic_id": "w4-string-operations-and-methods-core", + "subtopic_title": "Slicing with Step, Search, replace, join, strip, and the string Module", + "item_type": "ai_example", + "bucket": "aiExamples", + "selection_kind": "direct", + "search_text": "Check lowercase letters with `.islower()`\nprint(\"amsterdam\".islower())\nprint(\"Amsterdam\".islower())\nprint(\"123\".islower())\n`.islower()` only returns `True` when the string contains at least one cased character and all cased characters are lowercase.\nTrue\nFalse\nFalse" + }, + { + "item_id": "manual-string-repetition", + "card_id": "w4-string-operations-and-methods", + "topic": "String Operations and Methods", + "subtopic_id": "w4-string-operations-and-methods-core", + "subtopic_title": "Slicing with Step, Search, replace, join, strip, and the string Module", + "item_type": "ai_example", + "bucket": "aiExamples", + "selection_kind": "direct", + "search_text": "Repeat text with string multiplication\nprint(3 * \"ha\")\nprint(\"ab\" * 2)\nBoth `n * text` and `text * n` repeat the string `n` times, which is a common concise exam pattern.\nhahaha\nabab" + }, + { + "item_id": "exam-intro_python_sample_final_24_25-4-w2-conditions", + "card_id": "w4-string-operations-and-methods", + "topic": "String Operations and Methods", + "subtopic_id": "", + "subtopic_title": "", + "item_type": "source_exam", + "bucket": "recommended", + "selection_kind": "source", + "search_text": "Which of the following code segments does NOT achieve the goal of returning a string with 10 digits by removing dashes?\nA\nB\nC\nD\nA\nStrings in Python are immutable. The .replace() method returns a new string but does not modify the original. Option A returns the original string with dashes because the result of .replace() was not assigned back to the variable." + }, + { + "item_id": "exam-intro_python_sample_final_24_25-22-w2-conditions", + "card_id": "w4-string-operations-and-methods", + "topic": "String Operations and Methods", + "subtopic_id": "", + "subtopic_title": "", + "item_type": "source_exam", + "bucket": "recommended", + "selection_kind": "source", + "search_text": "Which script, using the count string method, would print the value 1 for x = 'Amsterdam'?\nA\nB\nC\nD\nB\nThe count() method is a string method, not a standalone function. It is called using the dot notation on a string object." + }, + { + "item_id": "ks-5198d93ec1", + "card_id": "w4-string-operations-and-methods", + "topic": "String Operations and Methods", + "subtopic_id": "", + "subtopic_title": "", + "item_type": "source_lecture", + "bucket": "recommended", + "selection_kind": "source", + "search_text": "String Searching: find vs index\nBoth find() and index() search for a substring. The key difference is that find() returns -1 if the substring is not found, while index() raises a ValueError.\nBehavior when substring is missing\ns = 'abc'\nprint(s.find('z')) # -1\n# print(s.index('z')) # Raises ValueError" + }, + { + "item_id": "ks-f80f1bf556", + "card_id": "w4-string-operations-and-methods", + "topic": "String Operations and Methods", + "subtopic_id": "", + "subtopic_title": "", + "item_type": "source_lecture", + "bucket": "recommended", + "selection_kind": "source", + "search_text": "String Slicing with Step\nSlicing allows a third parameter 'step'. s[::2] takes every second character, while s[::-1] reverses the string.\nSlicing examples\ns = '01234567'\nprint(s[::4]) # '04'\nprint(s[::-2]) # '7531'" + }, + { + "item_id": "ks-cdb152720e", + "card_id": "w4-string-operations-and-methods", + "topic": "String Operations and Methods", + "subtopic_id": "", + "subtopic_title": "", + "item_type": "source_lecture", + "bucket": "recommended", + "selection_kind": "source", + "search_text": "The join Method\nThe join() method takes an iterable (like a list) and concatenates its elements using the string it is called on as a separator.\nJoining a list into a string\nwords = ['a', 'b', 'c']\nprint('-'.join(words)) # 'a-b-c'\nprint(''.join(words)) # 'abc'" + }, + { + "item_id": "ks-45aead894c", + "card_id": "w4-string-operations-and-methods", + "topic": "String Operations and Methods", + "subtopic_id": "", + "subtopic_title": "", + "item_type": "source_lecture", + "bucket": "recommended", + "selection_kind": "source", + "search_text": "The replace Method\nReplaces occurrences of a substring. It accepts an optional 'count' argument to limit the number of replacements.\nLimiting replacements\ns = 'aaaa'\nprint(s.replace('a', 'b', 2)) # 'bbaa'" + }, + { + "item_id": "ks-bdea67862f", + "card_id": "w4-string-operations-and-methods", + "topic": "String Operations and Methods", + "subtopic_id": "", + "subtopic_title": "", + "item_type": "source_lecture", + "bucket": "additional", + "selection_kind": "source", + "search_text": "The string Module\nThe 'string' module provides pre-defined constants like all lowercase letters, digits, and punctuation.\nImporting string constants\nimport string\nprint(string.ascii_lowercase) # 'abcdef...'\nprint(string.digits) # '0123456789'" + }, + { + "item_id": "ks-e4dc502d3e", + "card_id": "w4-string-operations-and-methods", + "topic": "String Operations and Methods", + "subtopic_id": "", + "subtopic_title": "", + "item_type": "source_lecture", + "bucket": "additional", + "selection_kind": "source", + "search_text": "String Stripping\nstrip() removes leading and trailing characters. lstrip() and rstrip() target the left and right sides respectively.\nStripping whitespace and characters\ns = ' abc '\nprint(s.strip()) # 'abc'\ns2 = 'eeabcdee'\nprint(s2.strip('e')) # 'abcd'" + }, + { + "item_id": "aiq-1", + "card_id": "w4-string-formatting", + "topic": "String Formatting", + "subtopic_id": "", + "subtopic_title": "", + "item_type": "ai_common_question", + "bucket": "aiQuestions", + "selection_kind": "direct", + "search_text": "How do you include literal curly braces {} in an f-string?\nIn f-strings, curly braces are escaped by doubling them ({{ and }}).\nF-strings" + }, + { + "item_id": "kp-1", + "card_id": "w4-string-formatting", + "topic": "String Formatting", + "subtopic_id": "w4-string-formatting-core", + "subtopic_title": "f-strings Basics, Formatting, and Debug Form", + "item_type": "key_point", + "bucket": "keyPoints", + "selection_kind": "direct", + "search_text": "F-strings (formatted string literals) allow embedding expressions inside curly braces {}. They are more readable than traditional concatenation." + }, + { + "item_id": "kp-1-d1", + "card_id": "w4-string-formatting", + "topic": "String Formatting", + "subtopic_id": "", + "subtopic_title": "", + "item_type": "key_point_detail", + "bucket": "keyPoints", + "selection_kind": "detail", + "search_text": "Simple f-string\nname = 'Jan'\nprint(f'{name} studies Python.') # 'Jan studies Python.'" + }, + { + "item_id": "kp-2", + "card_id": "w4-string-formatting", + "topic": "String Formatting", + "subtopic_id": "w4-string-formatting-core", + "subtopic_title": "f-strings Basics, Formatting, and Debug Form", + "item_type": "key_point", + "bucket": "keyPoints", + "selection_kind": "direct", + "search_text": "Using f'{var=}' is a convenient shortcut for debugging that prints both the variable name and its value." + }, + { + "item_id": "kp-2-d1", + "card_id": "w4-string-formatting", + "topic": "String Formatting", + "subtopic_id": "", + "subtopic_title": "", + "item_type": "key_point_detail", + "bucket": "keyPoints", + "selection_kind": "detail", + "search_text": "Debug shortcut\nval = 10\nprint(f'{val=}') # 'val=10'" + }, + { + "item_id": "kp-3", + "card_id": "w4-string-formatting", + "topic": "String Formatting", + "subtopic_id": "w4-string-formatting-core", + "subtopic_title": "f-strings Basics, Formatting, and Debug Form", + "item_type": "key_point", + "bucket": "keyPoints", + "selection_kind": "direct", + "search_text": "You can specify formatting after a colon, such as padding numbers with zeros." + }, + { + "item_id": "kp-3-d1", + "card_id": "w4-string-formatting", + "topic": "String Formatting", + "subtopic_id": "", + "subtopic_title": "", + "item_type": "key_point_detail", + "bucket": "keyPoints", + "selection_kind": "detail", + "search_text": "Zero-padding an integer\nnum = 7\nprint(f'{num:03d}') # '007'" + }, + { + "item_id": "ai-example-1", + "card_id": "w4-string-formatting", + "topic": "String Formatting", + "subtopic_id": "w4-string-formatting-core", + "subtopic_title": "f-strings Basics, Formatting, and Debug Form", + "item_type": "ai_example", + "bucket": "aiExamples", + "selection_kind": "direct", + "search_text": "Simple f-string\nname = 'Jan'\nprint(f'{name} studies Python.') # 'Jan studies Python.'\nF-strings (formatted string literals) allow embedding expressions inside curly braces {}. They are more readable than traditional concatenation." + }, + { + "item_id": "ai-example-2", + "card_id": "w4-string-formatting", + "topic": "String Formatting", + "subtopic_id": "w4-string-formatting-core", + "subtopic_title": "f-strings Basics, Formatting, and Debug Form", + "item_type": "ai_example", + "bucket": "aiExamples", + "selection_kind": "direct", + "search_text": "Debug shortcut\nval = 10\nprint(f'{val=}') # 'val=10'\nUsing f'{var=}' is a convenient shortcut for debugging that prints both the variable name and its value." + }, + { + "item_id": "ai-example-3", + "card_id": "w4-string-formatting", + "topic": "String Formatting", + "subtopic_id": "w4-string-formatting-core", + "subtopic_title": "f-strings Basics, Formatting, and Debug Form", + "item_type": "ai_example", + "bucket": "aiExamples", + "selection_kind": "direct", + "search_text": "Zero-padding an integer\nnum = 7\nprint(f'{num:03d}') # '007'\nYou can specify formatting after a colon, such as padding numbers with zeros." + }, + { + "item_id": "ks-72dda5450c", + "card_id": "w4-string-formatting", + "topic": "String Formatting", + "subtopic_id": "", + "subtopic_title": "", + "item_type": "source_lecture", + "bucket": "recommended", + "selection_kind": "source", + "search_text": "F-strings Basics\nF-strings (formatted string literals) allow embedding expressions inside curly braces {}. They are more readable than traditional concatenation.\nSimple f-string\nname = 'Jan'\nprint(f'{name} studies Python.') # 'Jan studies Python.'" + }, + { + "item_id": "ks-ea5a4acb43", + "card_id": "w4-string-formatting", + "topic": "String Formatting", + "subtopic_id": "", + "subtopic_title": "", + "item_type": "source_lecture", + "bucket": "recommended", + "selection_kind": "source", + "search_text": "F-strings Debugging\nUsing f'{var=}' is a convenient shortcut for debugging that prints both the variable name and its value.\nDebug shortcut\nval = 10\nprint(f'{val=}') # 'val=10'" + }, + { + "item_id": "ks-acb7f400b2", + "card_id": "w4-string-formatting", + "topic": "String Formatting", + "subtopic_id": "", + "subtopic_title": "", + "item_type": "source_lecture", + "bucket": "recommended", + "selection_kind": "source", + "search_text": "F-strings Formatting\nYou can specify formatting after a colon, such as padding numbers with zeros.\nZero-padding an integer\nnum = 7\nprint(f'{num:03d}') # '007'" + }, + { + "item_id": "manual-self", + "card_id": "w4-oop-fundamentals", + "topic": "OOP Fundamentals", + "subtopic_id": "", + "subtopic_title": "", + "item_type": "ai_common_question", + "bucket": "aiQuestions", + "selection_kind": "direct", + "search_text": "Why is `self` the first parameter of an instance method?\n`self` is the current object, so the method can read and update that object's attributes.\nclass Flight:\n def set_date(self, date):\n self.date = date" + }, + { + "item_id": "manual-method-call", + "card_id": "w4-oop-fundamentals", + "topic": "OOP Fundamentals", + "subtopic_id": "", + "subtopic_title": "", + "item_type": "ai_common_question", + "bucket": "aiQuestions", + "selection_kind": "direct", + "search_text": "Why does `obj.set_date(obj, x)` pass too many arguments?\nWhen you call a method on an object, Python passes the object as `self` automatically. Writing it again adds one argument too many.\nobj.set_date(x) # correct\nobj.set_date(obj, x) # too many args" + }, + { + "item_id": "manual-init-default", + "card_id": "w4-oop-fundamentals", + "topic": "OOP Fundamentals", + "subtopic_id": "", + "subtopic_title": "", + "item_type": "ai_common_question", + "bucket": "aiQuestions", + "selection_kind": "direct", + "search_text": "How do default values in `__init__` make constructor arguments optional?\nA default like `vehicle_mode='land'` can be omitted when the object is created, but the instance still receives that attribute value.\nclass Vehicle:\n def __init__(self, name, vehicle_mode='land'):\n self.name = name\n self.vehicle_mode = vehicle_mode" + }, + { + "item_id": "kp-1", + "card_id": "w4-oop-fundamentals", + "topic": "OOP Fundamentals", + "subtopic_id": "w4-oop-fundamentals-core", + "subtopic_title": "Class Definition, __init__, self, and Attribute Basics", + "item_type": "key_point", + "bucket": "keyPoints", + "selection_kind": "direct", + "search_text": "A class defines methods and attribute layout; `__init__` runs when you create an object and stores instance data on `self`." + }, + { + "item_id": "kp-1-d1", + "card_id": "w4-oop-fundamentals", + "topic": "OOP Fundamentals", + "subtopic_id": "", + "subtopic_title": "", + "item_type": "key_point_detail", + "bucket": "keyPoints", + "selection_kind": "detail", + "search_text": "Defining a simple class\nclass Car:\n def __init__(self, color):\n self.color = color" + }, + { + "item_id": "kp-2", + "card_id": "w4-oop-fundamentals", + "topic": "OOP Fundamentals", + "subtopic_id": "w4-oop-fundamentals-core", + "subtopic_title": "Class Definition, __init__, self, and Attribute Basics", + "item_type": "key_point", + "bucket": "keyPoints", + "selection_kind": "direct", + "search_text": "`self` refers to the current instance, so instance methods read and write data through `self.attr`." + }, + { + "item_id": "kp-2-d1", + "card_id": "w4-oop-fundamentals", + "topic": "OOP Fundamentals", + "subtopic_id": "", + "subtopic_title": "", + "item_type": "key_point_detail", + "bucket": "keyPoints", + "selection_kind": "detail", + "search_text": "Using self to access attributes\nclass Dog:\n def __init__(self, name):\n self.name = name\n def bark(self):\n return f'{self.name} says woof!'" + }, + { + "item_id": "kp-3", + "card_id": "w4-oop-fundamentals", + "topic": "OOP Fundamentals", + "subtopic_id": "w4-oop-fundamentals-core", + "subtopic_title": "Class Definition, __init__, self, and Attribute Basics", + "item_type": "key_point", + "bucket": "keyPoints", + "selection_kind": "direct", + "search_text": "`self.x` is per object; a class attribute is shared until an instance shadows it with its own value." + }, + { + "item_id": "kp-3-d1", + "card_id": "w4-oop-fundamentals", + "topic": "OOP Fundamentals", + "subtopic_id": "", + "subtopic_title": "", + "item_type": "key_point_detail", + "bucket": "keyPoints", + "selection_kind": "detail", + "search_text": "Shared class attribute\nclass Counter:\n count = 0\n def __init__(self):\n Counter.count += 1" + }, + { + "item_id": "kp-4", + "card_id": "w4-oop-fundamentals", + "topic": "OOP Fundamentals", + "subtopic_id": "w4-oop-fundamentals-core", + "subtopic_title": "Class Definition, __init__, self, and Attribute Basics", + "item_type": "key_point", + "bucket": "keyPoints", + "selection_kind": "direct", + "search_text": "Method calls pass `self` automatically: `obj.set_date(x)` is correct; `obj.set_date(obj, x)` passes one argument too many." + }, + { + "item_id": "ai-example-1", + "card_id": "w4-oop-fundamentals", + "topic": "OOP Fundamentals", + "subtopic_id": "w4-oop-fundamentals-core", + "subtopic_title": "Class Definition, __init__, self, and Attribute Basics", + "item_type": "ai_example", + "bucket": "aiExamples", + "selection_kind": "direct", + "search_text": "Defining a simple class\nclass Car:\n def __init__(self, color):\n self.color = color\nA class defines methods and attribute layout; `__init__` runs when you create an object and stores instance data on `self`." + }, + { + "item_id": "ai-example-2", + "card_id": "w4-oop-fundamentals", + "topic": "OOP Fundamentals", + "subtopic_id": "w4-oop-fundamentals-core", + "subtopic_title": "Class Definition, __init__, self, and Attribute Basics", + "item_type": "ai_example", + "bucket": "aiExamples", + "selection_kind": "direct", + "search_text": "Using self to access attributes\nclass Dog:\n def __init__(self, name):\n self.name = name\n def bark(self):\n return f'{self.name} says woof!'\n`self` refers to the current instance, so instance methods read and write data through `self.attr`." + }, + { + "item_id": "ai-example-3", + "card_id": "w4-oop-fundamentals", + "topic": "OOP Fundamentals", + "subtopic_id": "w4-oop-fundamentals-core", + "subtopic_title": "Class Definition, __init__, self, and Attribute Basics", + "item_type": "ai_example", + "bucket": "aiExamples", + "selection_kind": "direct", + "search_text": "Shared class attribute\nclass Counter:\n count = 0\n def __init__(self):\n Counter.count += 1\n`self.x` is per object; a class attribute is shared until an instance shadows it with its own value." + }, + { + "item_id": "ai-example-6", + "card_id": "w4-oop-fundamentals", + "topic": "OOP Fundamentals", + "subtopic_id": "w4-oop-fundamentals-core", + "subtopic_title": "Class Definition, __init__, self, and Attribute Basics", + "item_type": "ai_example", + "bucket": "aiExamples", + "selection_kind": "direct", + "search_text": "Subclassing `str`\n#\nclass New_str(str):\n def index(self, needle, start = 0):\n return self.find(needle, start)\n\na = New_str(\"abcd\")\nprint(a.upper()) \nprint(a.find(\"d\")) \nprint(a.find(\"e\")) \nprint(a.index(\"d\")) \nprint(a.index(\"e\"))\nYou can subclass a built-in type to add custom methods while keeping the original string behavior." + }, + { + "item_id": "manual-oop-attrs", + "card_id": "w4-oop-fundamentals", + "topic": "OOP Fundamentals", + "subtopic_id": "w4-oop-fundamentals-core", + "subtopic_title": "Class Definition, __init__, self, and Attribute Basics", + "item_type": "ai_example", + "bucket": "aiExamples", + "selection_kind": "direct", + "search_text": "Class attribute vs instance attribute\nclass Rectangle:\n units = 'cm'\n\n def __init__(self, width):\n self.width = width\n\nr1 = Rectangle(3)\nr2 = Rectangle(5)\nr2.units = 'm'\nprint(r1.units, r2.units)\n`self.width` is per object; `Class.units` is shared until an instance shadows it with its own attribute.\ncm m" + }, + { + "item_id": "manual-oop-constructor-defaults", + "card_id": "w4-oop-fundamentals", + "topic": "OOP Fundamentals", + "subtopic_id": "w4-oop-fundamentals-core", + "subtopic_title": "Class Definition, __init__, self, and Attribute Basics", + "item_type": "ai_example", + "bucket": "aiExamples", + "selection_kind": "direct", + "search_text": "Constructor defaults belong in `__init__` parameters\nclass Vehicle:\n def __init__(self, name, mode=\"land\"):\n self.name = name\n self.mode = mode\n\ncar = Vehicle(\"Mazda\")\nprint(car.name, car.mode)\nDefault constructor arguments let an instance omit optional information while still giving `self` a predictable initial state.\nMazda land" + }, + { + "item_id": "manual-oop-state-compare", + "card_id": "w4-oop-fundamentals", + "topic": "OOP Fundamentals", + "subtopic_id": "w4-oop-fundamentals-core", + "subtopic_title": "Class Definition, __init__, self, and Attribute Basics", + "item_type": "ai_example", + "bucket": "aiExamples", + "selection_kind": "direct", + "search_text": "Trace `self` state across multiple method calls\nclass Book:\n def __init__(self, title):\n self.title = title\n self.scores = []\n\n def add_review(self, score):\n self.scores.append(score)\n\n def average(self):\n return sum(self.scores) / len(self.scores)\n\n def better_than(self, other):\n return self.average() > other.average()\n\nbook_1 = Book(\"A\")\nbook_2 = Book(\"B\")\nfor score in [5, 3, 3]:\n book_1.add_review(score)\nfor score in [4, 4, 4]:\n book_2.add_review(score)\nprint(book_1.better_than(book_2))\nExam OOP reasoning often hinges on updating `self` in one method and then comparing derived state in a later method call.\nFalse" + }, + { + "item_id": "exam-intro_python_sample_final_24_25-1-w5-pandas-core-structures", + "card_id": "w4-oop-fundamentals", + "topic": "OOP Fundamentals", + "subtopic_id": "", + "subtopic_title": "", + "item_type": "source_exam", + "bucket": "recommended", + "selection_kind": "source", + "search_text": "You'd like to define a class called Vehicle. It should have two attributes: name and mode, which you want to be initialized during object creation. The name attribute can be any string, and it must be passed to the object during creation. The mode attribute is also a string, but it doesn't necessarily need to be passed to the object constructor. If it isn't specified at object construction, then the mode attribute should be equal to the string \"land\". Which of the following code segments achieves what you want?\nA\nB\nC\nD\nA\nIn Python, default parameter values in the __init__ method allow for optional arguments during object creation. Option A correctly assigns the parameters to instance attributes." + }, + { + "item_id": "exam-intro_python_sample_final_24_25-2-w5-pandas-core-structures", + "card_id": "w4-oop-fundamentals", + "topic": "OOP Fundamentals", + "subtopic_id": "", + "subtopic_title": "", + "item_type": "source_exam", + "bucket": "recommended", + "selection_kind": "source", + "search_text": "Suppose that we create a Book object and call its add_review method three times, like this: book_1 = Book(\"The Lightning Thief\", \"Rick Riordan\"), book_1.add_review(5), book_1.add_review(3), book_1.add_review(3). What will then the following command print to the screen? print(book_1.show_rating())\nA\nB\nC\nD\nA\nThe average of scores [5, 3, 3] is 11 / 3 = 3.666... Using round(..., 1) results in 3.7." + }, + { + "item_id": "exam-Trial final exam Introduction to Python-1-w4-oop-fundamentals", + "card_id": "w4-oop-fundamentals", + "topic": "OOP Fundamentals", + "subtopic_id": "", + "subtopic_title": "", + "item_type": "source_exam", + "bucket": "recommended", + "selection_kind": "source", + "search_text": "You'd like to define a class called Vehicle. It should have two attributes: \"name\" and \"mode\", which you want to be initialized at the time of object construction.\n\nThe \"name\" attribute can be any string, and it must be passed to the object constructor. The \"mode\" attribute is also a string, but it doesn't necessarily need to be passed to the object constructor. If it isn't specified at object construction, then the \"mode\" attribute should be equal to \"land\".\n\nFor example, if we create a Vehicle object as:\nmy_car = Vehicle(\"Mazda\")\nthen the following two conditions should both be true:\nmy_car.name == \"Mazda\"\nmy_car.mode == \"land\"\n\nWhich of the following code segments achieves what you want?\na\nb\nc\nd\na\nOption A correctly uses `self` as the first parameter of the `__init__` method, provides a default value for `vehicle_mode` (\"land\"), and properly assigns both arguments to instance attributes." + }, + { + "item_id": "exam-Test Exam 07-06-22-1-w4-oop-fundamentals", + "card_id": "w4-oop-fundamentals", + "topic": "OOP Fundamentals", + "subtopic_id": "", + "subtopic_title": "", + "item_type": "source_exam", + "bucket": "recommended", + "selection_kind": "source", + "search_text": "Given the class definition above, trying to execute the following two code lines will result in a Python error.\nmy_flight = Flight(\"KLM\", \"Amsterdam\", \"Paris\") # Code line 1\nmy_flight.set_date(my_flight, \"29-02-2022\") # Code line 2\n\nWhy?\na\nb\nc\nd\na\nIn Python, when calling a method on an object, the object itself is automatically passed as the first argument (self). Passing my_flight explicitly results in too many arguments being passed to set_date." + }, + { + "item_id": "exam-Trial final exam Introduction to Python-2-w4-oop-fundamentals", + "card_id": "w4-oop-fundamentals", + "topic": "OOP Fundamentals", + "subtopic_id": "", + "subtopic_title": "", + "item_type": "source_exam", + "bucket": "recommended", + "selection_kind": "source", + "search_text": "Take a look at the following class definition.\n\nSuppose that we create a Book object and call its add_review method three times, like this:\nbook_1 = Book(\"The Lightning Thief\", \"Rick Riordan\")\nbook_1.add_review(5)\nbook_1.add_review(3)\nbook_1.add_review(3)\n\nWhat will then the following command print to the screen?\nprint(book_1.show_rating())\na\nb\nc\nd\na\nThe list of review scores is [5, 3, 3]. The sum is 11, and the length is 3. 11 / 3 is approximately 3.666... Using `round(..., 1)` rounds this float to one decimal place, resulting in 3.7." + }, + { + "item_id": "exam-Test Exam 07-06-22-2-w4-oop-fundamentals", + "card_id": "w4-oop-fundamentals", + "topic": "OOP Fundamentals", + "subtopic_id": "", + "subtopic_title": "", + "item_type": "source_exam", + "bucket": "recommended", + "selection_kind": "source", + "search_text": "Suppose that you also want to write a method called compare that compares the book to another book and gives a recommendation for which one to read. A book is better than another book if its average review score is higher than the second book's and it has at least as many reviews as the second book.\n\nThe compare method should return the title of the better book. If neither book is better than the other, then it should return None.\n\nFor simplicity, you can assume that both books have at least one review already.\n\nWhich method definition achieves what you want?\na\nb\nc\nd\nb\nOption A fails because its 'elif not avg_better:' condition triggers simply when the other book has an equal or better score, but it returns the other book's title without checking if the other book has at least as many reviews as the first book. Option B checks both pairs (self, other) and (other, self) against the requirements, returning the better one, or implicitly returning None if neither is better." + }, + { + "item_id": "ks-06b21ad349", + "card_id": "w4-oop-fundamentals", + "topic": "OOP Fundamentals", + "subtopic_id": "", + "subtopic_title": "", + "item_type": "source_lecture", + "bucket": "recommended", + "selection_kind": "source", + "search_text": "Class Definition and __init__\nA class is a blueprint. The __init__ method is the constructor called automatically when a new object is created to initialize attributes.\nDefining a simple class\nclass Car:\n def __init__(self, color):\n self.color = color" + }, + { + "item_id": "ks-9e278d1ee6", + "card_id": "w4-oop-fundamentals", + "topic": "OOP Fundamentals", + "subtopic_id": "", + "subtopic_title": "", + "item_type": "source_lecture", + "bucket": "recommended", + "selection_kind": "source", + "search_text": "The self Parameter\nIn class methods, 'self' refers to the specific instance of the object. It must be the first parameter of any instance method.\nUsing self to access attributes\nclass Dog:\n def __init__(self, name):\n self.name = name\n def bark(self):\n return f'{self.name} says woof!'" + }, + { + "item_id": "ks-5cbba26b09", + "card_id": "w4-oop-fundamentals", + "topic": "OOP Fundamentals", + "subtopic_id": "", + "subtopic_title": "", + "item_type": "source_lecture", + "bucket": "recommended", + "selection_kind": "source", + "search_text": "Class vs Instance Attributes\nInstance attributes (self.x) are unique to each object. Class attributes are defined outside methods and shared by all instances of the class.\nShared class attribute\nclass Counter:\n count = 0\n def __init__(self):\n Counter.count += 1" + }, + { + "item_id": "cs-0d319e4faf", + "card_id": "w4-oop-fundamentals", + "topic": "OOP Fundamentals", + "subtopic_id": "", + "subtopic_title": "", + "item_type": "source_notebook", + "bucket": "recommended", + "selection_kind": "source", + "search_text": "class Rectangle:\nclass Rectangle:\n total_size = 0\n def __init__(self, length, width=1):\n self.length = length\n self.width = width\n Rectangle.total_size += self.length * self.width\n print(f'{self.length} by {self.width} created, {Rectangle.total_size = }')\n def size(self, data_type=int):\n return f\"The size = {data_type(self.length * self.width)}.\"\n def __del__(self):\n Rectangle.total_size -= self.length * self.width\n print(f'{self.length} by {self.width} deleted, {Rectangle.total_size = }')\n \nprint(Rectangle.total_size)\nrectangle_1 = Rectangle(2,3) \nrectangle_2 = Rectangle(2)\ndel rectangle_1 \ndel rectangle_2\n0\n2 by 3 created, Rectangle.total_size = 6\n2 by 1 created, Rectangle.total_size = 8\n2 by 3 deleted, Rectangle.total_size = 2\n2 by 1 deleted, Rectangle.total_size = 0" + }, + { + "item_id": "cs-30e53467b8", + "card_id": "w4-oop-fundamentals", + "topic": "OOP Fundamentals", + "subtopic_id": "", + "subtopic_title": "", + "item_type": "source_notebook", + "bucket": "additional", + "selection_kind": "source", + "search_text": "class Rectangle:\nclass Rectangle:\n total_size = 0\n def __init__(self, length, width=1):\n self.length = length\n self.width = width\n Rectangle.total_size += self.length * self.width\n print(f'rectangle {self.length} by {self.width} created\\n{Rectangle.total_size = }')\n def size(self, data_type=int):\n return f\"The size = {data_type(self.length * self.width)}.\"\n def __del__(self):\n Rectangle.total_size -= self.length * self.width\n print(f'rectangle {self.length} by {self.width} deleted\\n{Rectangle.total_size = }')\n \nprint(Rectangle.total_size)\nrectangle_1 = Rectangle(2,3)\nrectangle_2 = Rectangle(3)\nrectangle_3 = Rectangle(2,2)\n\ndel rectangle_1\ndel rectangle_3\ndel rectangle_2\n0\nrectangle 2 by 3 created\nRectangle.total_size = 6\nrectangle 3 by 1 created\nRectangle.total_size = 9\nrectangle 2 by 2 created\nRectangle.total_size = 13\nrectangle 2 by 3 deleted\nRectangle.total_size = 7\nrectangle 2 by 2 deleted\nRectangle.total_size = 3\nrectangle 3 by 1 deleted\nRectangle.total_size = 0" + }, + { + "item_id": "aiq-1", + "card_id": "w4-error-handling", + "topic": "Error Handling", + "subtopic_id": "", + "subtopic_title": "", + "item_type": "ai_common_question", + "bucket": "aiQuestions", + "selection_kind": "direct", + "search_text": "RuntimeError: dictionary changed size during iteration\nAdding or deleting dict entries while iterating over it causes RuntimeError" + }, + { + "item_id": "kp-1", + "card_id": "w4-error-handling", + "topic": "Error Handling", + "subtopic_id": "w4-error-handling-core", + "subtopic_title": "try/except and raise", + "item_type": "key_point", + "bucket": "keyPoints", + "selection_kind": "direct", + "search_text": "The try block lets you test a block of code for errors, and the except block lets you handle the error without the program crashing." + }, + { + "item_id": "kp-1-d1", + "card_id": "w4-error-handling", + "topic": "Error Handling", + "subtopic_id": "", + "subtopic_title": "", + "item_type": "key_point_detail", + "bucket": "keyPoints", + "selection_kind": "detail", + "search_text": "Handling a ValueError\ns = 'abc'\ntry:\n idx = s.index('z')\nexcept ValueError:\n idx = -1" + }, + { + "item_id": "kp-2", + "card_id": "w4-error-handling", + "topic": "Error Handling", + "subtopic_id": "w4-error-handling-core", + "subtopic_title": "try/except and raise", + "item_type": "key_point", + "bucket": "keyPoints", + "selection_kind": "direct", + "search_text": "You can use 'raise' to manually trigger an exception when a specific condition occurs." + }, + { + "item_id": "kp-2-d1", + "card_id": "w4-error-handling", + "topic": "Error Handling", + "subtopic_id": "", + "subtopic_title": "", + "item_type": "key_point_detail", + "bucket": "keyPoints", + "selection_kind": "detail", + "search_text": "Raising an error\ndef check_positive(n):\n if n < 0:\n raise ValueError('Number must be positive')\n return n" + }, + { + "item_id": "ai-example-1", + "card_id": "w4-error-handling", + "topic": "Error Handling", + "subtopic_id": "w4-error-handling-core", + "subtopic_title": "try/except and raise", + "item_type": "ai_example", + "bucket": "aiExamples", + "selection_kind": "direct", + "search_text": "Handling a ValueError\ns = 'abc'\ntry:\n idx = s.index('z')\nexcept ValueError:\n idx = -1\nThe try block lets you test a block of code for errors, and the except block lets you handle the error without the program crashing." + }, + { + "item_id": "ai-example-2", + "card_id": "w4-error-handling", + "topic": "Error Handling", + "subtopic_id": "w4-error-handling-core", + "subtopic_title": "try/except and raise", + "item_type": "ai_example", + "bucket": "aiExamples", + "selection_kind": "direct", + "search_text": "Raising an error\ndef check_positive(n):\n if n < 0:\n raise ValueError('Number must be positive')\n return n\nYou can use 'raise' to manually trigger an exception when a specific condition occurs." + }, + { + "item_id": "ai-example-3", + "card_id": "w4-error-handling", + "topic": "Error Handling", + "subtopic_id": "w4-error-handling-core", + "subtopic_title": "try/except and raise", + "item_type": "ai_example", + "bucket": "aiExamples", + "selection_kind": "direct", + "search_text": "def my_find(s,needle):\ndef my_find(s,needle):\n if (result := s.find(needle)) == -1:\n raise ValueError(\"substring not found\")\n return result\ns1 ='abcdefghabcdefgh'\nprint(my_find(s1, 'e'))\nprint(my_find(s1, 'i'))\nTrace the returned value, not just what gets printed while the function runs." + }, + { + "item_id": "ai-example-4", + "card_id": "w4-error-handling", + "topic": "Error Handling", + "subtopic_id": "w4-error-handling-core", + "subtopic_title": "try/except and raise", + "item_type": "ai_example", + "bucket": "aiExamples", + "selection_kind": "direct", + "search_text": "def my_index(s,needle):\ndef my_index(s,needle):\n try:\n result = s.index(needle)\n except:\n result = -1\n return result\ns1 ='abcdefghabcdefgh'\nprint(my_index(s1, 'e'))\nprint(my_index(s1, 'i'))\nTrace the returned value, not just what gets printed while the function runs." + }, + { + "item_id": "ks-2c73fabc68", + "card_id": "w4-error-handling", + "topic": "Error Handling", + "subtopic_id": "", + "subtopic_title": "", + "item_type": "source_lecture", + "bucket": "recommended", + "selection_kind": "source", + "search_text": "Error Handling: try-except\nThe try block lets you test a block of code for errors, and the except block lets you handle the error without the program crashing.\nHandling a ValueError\ns = 'abc'\ntry:\n idx = s.index('z')\nexcept ValueError:\n idx = -1" + }, + { + "item_id": "ks-40d373c410", + "card_id": "w4-error-handling", + "topic": "Error Handling", + "subtopic_id": "", + "subtopic_title": "", + "item_type": "source_lecture", + "bucket": "recommended", + "selection_kind": "source", + "search_text": "The raise Keyword\nYou can use 'raise' to manually trigger an exception when a specific condition occurs.\nRaising an error\ndef check_positive(n):\n if n < 0:\n raise ValueError('Number must be positive')\n return n" + }, + { + "item_id": "manual-series-vs-dataframe", + "card_id": "w5-pandas-core-structures", + "topic": "Pandas Core Structures", + "subtopic_id": "", + "subtopic_title": "", + "item_type": "ai_common_question", + "bucket": "aiQuestions", + "selection_kind": "direct", + "search_text": "What does `df['A']` return versus `df[['A']]`?\n`df['A']` returns a `Series`; `df[['A']]` returns a one-column `DataFrame`.\ndf['A']\ndf[['A']]" + }, + { + "item_id": "manual-series-index", + "card_id": "w5-pandas-core-structures", + "topic": "Pandas Core Structures", + "subtopic_id": "", + "subtopic_title": "", + "item_type": "ai_common_question", + "bucket": "aiQuestions", + "selection_kind": "direct", + "search_text": "What index does a `Series` get if you do not provide one explicitly?\nPandas uses the default integer index `0, 1, 2, ...`.\ns = pd.Series([10, 20, 30])" + }, + { + "item_id": "manual-df-constructor", + "card_id": "w5-pandas-core-structures", + "topic": "Pandas Core Structures", + "subtopic_id": "", + "subtopic_title": "", + "item_type": "ai_common_question", + "bucket": "aiQuestions", + "selection_kind": "direct", + "search_text": "How do you build a `DataFrame` from a dict of column names to lists?\nEach key becomes a column, and each list supplies that column's values row by row.\ndf = pd.DataFrame({'A': [1, 2], 'B': [3, 4]})" + }, + { + "item_id": "kp-manual-series-default-index", + "card_id": "w5-pandas-core-structures", + "topic": "Pandas Core Structures", + "subtopic_id": "", + "subtopic_title": "", + "item_type": "key_point", + "bucket": "keyPoints", + "selection_kind": "direct", + "search_text": "A `Series` is 1D labeled data; if you do not supply an index, pandas uses `0, 1, 2, ...`." + }, + { + "item_id": "kp-manual-df-constructor", + "card_id": "w5-pandas-core-structures", + "topic": "Pandas Core Structures", + "subtopic_id": "", + "subtopic_title": "", + "item_type": "key_point", + "bucket": "keyPoints", + "selection_kind": "direct", + "search_text": "A `DataFrame` is a 2D table; a dict of column names to equal-length lists is the standard constructor pattern." + }, + { + "item_id": "kp-manual-series-vs-df", + "card_id": "w5-pandas-core-structures", + "topic": "Pandas Core Structures", + "subtopic_id": "", + "subtopic_title": "", + "item_type": "key_point", + "bucket": "keyPoints", + "selection_kind": "direct", + "search_text": "`df['A']` gives a `Series`, while `df[['A']]` gives a one-column `DataFrame`." + }, + { + "item_id": "manual-pandas-import", + "card_id": "w5-pandas-core-structures", + "topic": "Pandas Core Structures", + "subtopic_id": "w5-pandas-core-structures-core", + "subtopic_title": "Series, DataFrame, and Creation Patterns", + "item_type": "ai_example", + "bucket": "aiExamples", + "selection_kind": "direct", + "search_text": "Import pandas with the conventional alias\nimport pandas as pd\nUse the `pd` alias so constructors and methods stay short and readable during the exam." + }, + { + "item_id": "manual-pandas-series", + "card_id": "w5-pandas-core-structures", + "topic": "Pandas Core Structures", + "subtopic_id": "w5-pandas-core-structures-core", + "subtopic_title": "Series, DataFrame, and Creation Patterns", + "item_type": "ai_example", + "bucket": "aiExamples", + "selection_kind": "direct", + "search_text": "Create a `Series` from a list\ns = pd.Series([153, 160, 150], name='Length')\nprint(s)\nWithout an explicit index, pandas labels the rows `0, 1, 2, ...`.\n0 153\n1 160\n2 150\nName: Length, dtype: int64" + }, + { + "item_id": "manual-pandas-df", + "card_id": "w5-pandas-core-structures", + "topic": "Pandas Core Structures", + "subtopic_id": "w5-pandas-core-structures-core", + "subtopic_title": "Series, DataFrame, and Creation Patterns", + "item_type": "ai_example", + "bucket": "aiExamples", + "selection_kind": "direct", + "search_text": "Build a `DataFrame` from a dict of columns\ndf = pd.DataFrame({'A': [1, 2], 'B': [3, 4]})\nprint(df)\nEach dict key becomes a column and the lists provide the row values for that column.\n A B\n0 1 3\n1 2 4" + }, + { + "item_id": "manual-pandas-select-shape", + "card_id": "w5-pandas-core-structures", + "topic": "Pandas Core Structures", + "subtopic_id": "w5-pandas-core-structures-core", + "subtopic_title": "Series, DataFrame, and Creation Patterns", + "item_type": "ai_example", + "bucket": "aiExamples", + "selection_kind": "direct", + "search_text": "`df['A']` versus `df[['A']]`\ndf['A'] # Series\ndf[['A']] # one-column DataFrame\nCheck the brackets carefully: one pair returns a `Series`, two pairs return a `DataFrame`." + }, + { + "item_id": "exam-intro_python_sample_final_24_25-5-w4-string-fundamentals", + "card_id": "w5-pandas-core-structures", + "topic": "Pandas Core Structures", + "subtopic_id": "", + "subtopic_title": "", + "item_type": "source_exam", + "bucket": "recommended", + "selection_kind": "source", + "search_text": "You have a pandas DataFrame called df with columns \"A\" and \"B\". You'd like to create a column called \"C\", which contains the sum of the numbers in columns \"A\" and \"B\". Which of the following code lines will achieve what you want?\nA\nB\nC\nD\nA\nVectorized addition in Pandas is performed by adding series together. Using .loc[:, 'C'] correctly assigns the result to a new column for all rows." + }, + { + "item_id": "exam-Test Exam 07-06-22-5-w5-pandas-core-structures", + "card_id": "w5-pandas-core-structures", + "topic": "Pandas Core Structures", + "subtopic_id": "", + "subtopic_title": "", + "item_type": "source_exam", + "bucket": "recommended", + "selection_kind": "source", + "search_text": "You have a pandas Series called s, which contains floats. You'd like to create a new Series, in which each element is equal to the square of the difference between the corresponding element in s and the mean of the elements in s.\n\nFor example, if s is the Series:\n0 2.0\n1 2.0\n2 3.0\n3 5.0\ndtype: float64\n\nthen you want the new Series to be:\n0 1.0\n1 1.0\n2 0.0\n3 4.0\ndtype: float64\n\nWhich of the following code segments does not achieve what you want?\na\nb\nc\nd\na\nThe map() method on a Series expects a function, dictionary, or another Series. If passed a Series, it uses the values of the caller (s) to look up indices in the passed Series. This will lead to unexpected results (looking up float values like 2.0 as indices) instead of applying the mathematical transformation. The other options correctly perform the element-wise operation." + }, + { + "item_id": "exam-Trial final exam Introduction to Python-5-w5-pandas-core-structures", + "card_id": "w5-pandas-core-structures", + "topic": "Pandas Core Structures", + "subtopic_id": "", + "subtopic_title": "", + "item_type": "source_exam", + "bucket": "recommended", + "selection_kind": "source", + "search_text": "You have a pandas DataFrame called df. It has a column called \"A\" and a column called \"B\". Both contain numbers.\n\nYou'd like to create a column called \"C\", which contains the sum of the numbers in columns \"A\" and \"B\". Which of the following code lines will achieve what you want?\na\nb\nc\nd\na\nPandas supports vectorized operations. You can add two Series (columns) together element-wise by directly using the `+` operator." + }, + { + "item_id": "ks-052ed25923", + "card_id": "w5-pandas-core-structures", + "topic": "Pandas Core Structures", + "subtopic_id": "", + "subtopic_title": "", + "item_type": "source_lecture", + "bucket": "recommended", + "selection_kind": "source", + "search_text": "pd.Series\nA one-dimensional labeled array. If no index is provided, it defaults to integers starting from 0.\nCreating a Series from a list\nimport pandas as pd\ns1 = pd.Series([153, 160, 150], name='Length')" + }, + { + "item_id": "ks-9a5d2c05fb", + "card_id": "w5-pandas-core-structures", + "topic": "Pandas Core Structures", + "subtopic_id": "", + "subtopic_title": "", + "item_type": "source_lecture", + "bucket": "recommended", + "selection_kind": "source", + "search_text": "pd.DataFrame\nA two-dimensional tabular data structure. Most commonly created from a dictionary where keys are column names and values are lists.\nCreating from dictionary\nd = {'Name': ['A', 'B'], 'Weight': [55, 70]}\ndf = pd.DataFrame(d, index=['First', 'Second'])" + }, + { + "item_id": "ks-75cf35c8b4", + "card_id": "w5-pandas-core-structures", + "topic": "Pandas Core Structures", + "subtopic_id": "", + "subtopic_title": "", + "item_type": "source_lecture", + "bucket": "recommended", + "selection_kind": "source", + "search_text": "DatetimeIndex\nA specialized index for dates. Elements have attributes like .year, .month, and .day.\nFiltering by month\ndf.loc[[r for r in df.index if r.month == 4]]" + }, + { + "item_id": "cs-82ef14b9d5", + "card_id": "w5-pandas-core-structures", + "topic": "Pandas Core Structures", + "subtopic_id": "", + "subtopic_title": "", + "item_type": "source_notebook", + "bucket": "recommended", + "selection_kind": "source", + "search_text": "import pandas as pd\nimport pandas as pd\nd1 = {'A':[2, 5, 6], 'B':[3, 4, 7]}\ndf1 = pd.DataFrame (d1)\nprint(df1)\n\ndf2 = df1.loc[:]\ndf2 += 1\nprint(df2)\nA B\n0 2 3\n1 5 4\n2 6 7\n A B\n0 3 4\n1 6 5\n2 7 8" + }, + { + "item_id": "cs-49cf15967e", + "card_id": "w5-pandas-core-structures", + "topic": "Pandas Core Structures", + "subtopic_id": "", + "subtopic_title": "", + "item_type": "source_notebook", + "bucket": "additional", + "selection_kind": "source", + "search_text": "import pandas as pd\nimport pandas as pd\nd1 = {'A':[2, 5, 6], 'B':[3, 4, 7]}\ndf1 = pd.DataFrame (d1)\nprint(df1)\n\ndf2 = df1.loc[:]\ndf2.A += 1\nprint(df2)\nA B\n0 2 3\n1 5 4\n2 6 7\n A B\n0 3 3\n1 6 4\n2 7 7" + }, + { + "item_id": "cs-c4c296595e", + "card_id": "w5-pandas-core-structures", + "topic": "Pandas Core Structures", + "subtopic_id": "", + "subtopic_title": "", + "item_type": "source_notebook", + "bucket": "additional", + "selection_kind": "source", + "search_text": "import pandas as pd\nimport pandas as pd\nd1 = {'A':[2, 5, 6], 'B':[3, 4, 7]}\ndf1 = pd.DataFrame (d1)\nprint(df1)\n\ndf2 = df1.loc[:]\ndf2.loc[1] += 1\nprint(df2)\nA B\n0 2 3\n1 5 4\n2 6 7\n A B\n0 2 3\n1 6 5\n2 6 7" + }, + { + "item_id": "cs-8bae99d6de", + "card_id": "w5-pandas-core-structures", + "topic": "Pandas Core Structures", + "subtopic_id": "", + "subtopic_title": "", + "item_type": "source_notebook", + "bucket": "additional", + "selection_kind": "source", + "search_text": "import pandas as pd\nimport pandas as pd\nd1 = {'A':[2, 5, 6], 'B':[3, 4, 7]}\ndf1 = pd.DataFrame (d1)\nprint(df1)\n\ndf2 = df1.loc[:]\ndf2.A += [1, 2]\nprint(df2)\nA B\n0 2 3\n1 5 4\n2 6 7" + }, + { + "item_id": "cs-cdfd529b3d", + "card_id": "w5-pandas-core-structures", + "topic": "Pandas Core Structures", + "subtopic_id": "", + "subtopic_title": "", + "item_type": "source_notebook", + "bucket": "additional", + "selection_kind": "source", + "search_text": "import pandas as pd\nimport pandas as pd\nd1 = {'A':[2, 5, 6], 'B':[3, 4, 7]}\ndf1 = pd.DataFrame (d1)\nprint(df1)\n\ndf2 = df1.loc[:]\ndf2.A += [1, 2, 3]\nprint(df2)\nA B\n0 2 3\n1 5 4\n2 6 7\n A B\n0 3 3\n1 7 4\n2 9 7" + }, + { + "item_id": "cs-2e178eda82", + "card_id": "w5-pandas-core-structures", + "topic": "Pandas Core Structures", + "subtopic_id": "", + "subtopic_title": "", + "item_type": "source_notebook", + "bucket": "additional", + "selection_kind": "source", + "search_text": "import pandas as pd\nimport pandas as pd\nd1 = {'A':[2, 5, 6], 'B':[3, 4, 7]}\ndf1 = pd.DataFrame (d1)\nprint(df1)\n\ndf2 = df1.loc[:]\ndf2.loc[[1,2]] += 1\nprint(df2)\nA B\n0 2 3\n1 5 4\n2 6 7\n A B\n0 2 3\n1 6 5\n2 7 8" + }, + { + "item_id": "cs-b3e0b57d7a", + "card_id": "w5-pandas-core-structures", + "topic": "Pandas Core Structures", + "subtopic_id": "", + "subtopic_title": "", + "item_type": "source_notebook", + "bucket": "additional", + "selection_kind": "source", + "search_text": "import pandas as pd\nimport pandas as pd\nd1 = {'A':[2, 5, 6], 'B':[3, 4, 7]}\ndf1 = pd.DataFrame (d1)\nprint(df1)\n\ndf2 = df1.loc[:]\ndf2.A = df2.A.map(lambda x: 3 * x)\nprint(df2)\nA B\n0 2 3\n1 5 4\n2 6 7\n A B\n0 6 3\n1 15 4\n2 18 7" + }, + { + "item_id": "cs-e6b6bd65f0", + "card_id": "w5-pandas-core-structures", + "topic": "Pandas Core Structures", + "subtopic_id": "", + "subtopic_title": "", + "item_type": "source_notebook", + "bucket": "additional", + "selection_kind": "source", + "search_text": "import pandas as pd\nimport pandas as pd\nd1 = {'A':[2, 5, 6], 'B':[3, 4, 7]}\ndf1 = pd.DataFrame (d1)\nprint(df1)\n\ndf2 = df1.loc[:]\ndf2.loc[1] = df2.loc[1].map(lambda x: 3 * x)\nprint(df2)\nA B\n0 2 3\n1 5 4\n2 6 7\n A B\n0 2 3\n1 15 12\n2 6 7" + }, + { + "item_id": "cs-8ec741987c", + "card_id": "w5-pandas-core-structures", + "topic": "Pandas Core Structures", + "subtopic_id": "", + "subtopic_title": "", + "item_type": "source_notebook", + "bucket": "additional", + "selection_kind": "source", + "search_text": "import pandas as pd\nimport pandas as pd\nd1 = {'A':[2, 5, 6], 'B':[3, 4, 7]}\ndf1 = pd.DataFrame (d1)\nprint(df1)\n\ndf2 = df1.loc[:]\ndf2 += pd.DataFrame({'A':[1, 2, 3], 'B':[4, 5, 6]})\nprint(df2)\nA B\n0 2 3\n1 5 4\n2 6 7\n A B\n0 3 7\n1 7 9\n2 9 13" + }, + { + "item_id": "cs-b069af91f4", + "card_id": "w5-pandas-core-structures", + "topic": "Pandas Core Structures", + "subtopic_id": "", + "subtopic_title": "", + "item_type": "source_notebook", + "bucket": "additional", + "selection_kind": "source", + "search_text": "import pandas as pd\nimport pandas as pd\nd1 = {'A':[2, 5, 6], 'B':[3, 4, 7]}\ndf1 = pd.DataFrame (d1)\nprint(df1)\n\ndf2 = df1.loc[:]\ndf2 += pd.DataFrame({'A':[2, 5, 6], 'B':[3, 4, 7]}, index=[4,5,6])\nprint(df2)\nA B\n0 2 3\n1 5 4\n2 6 7\n A B\n0 NaN NaN\n1 NaN NaN\n2 NaN NaN" + }, + { + "item_id": "aiq-1", + "card_id": "w5-inspecting-and-selecting-data", + "topic": "Inspecting and Selecting Data", + "subtopic_id": "", + "subtopic_title": "", + "item_type": "ai_common_question", + "bucket": "aiQuestions", + "selection_kind": "direct", + "search_text": "What happens if you run print(df.iloc[5, 2]) on a DataFrame with only 3 rows?\nUnlike slicing, accessing a specific single position with .iloc that is out of bounds raises an IndexError.\nSelection with iloc" + }, + { + "item_id": "aiq-5", + "card_id": "w5-inspecting-and-selecting-data", + "topic": "Inspecting and Selecting Data", + "subtopic_id": "", + "subtopic_title": "", + "item_type": "ai_common_question", + "bucket": "aiQuestions", + "selection_kind": "direct", + "search_text": "UnboundLocalError\nIf a name appears on the left side of assignment ANYWHERE in a function, Python treats it as local THROUGHOUT the function body \u2014 even before the assignment line" + }, + { + "item_id": "kp-1", + "card_id": "w5-inspecting-and-selecting-data", + "topic": "Inspecting and Selecting Data", + "subtopic_id": "w5-inspecting-and-selecting-data-core", + "subtopic_title": "head, tail, describe, loc, iloc, Result Types, and Boolean Indexing", + "item_type": "key_point", + "bucket": "keyPoints", + "selection_kind": "direct", + "search_text": "Use .head(n) for the first n rows, .tail(n) for the last n rows, and .describe() for summary statistics." + }, + { + "item_id": "kp-1-d1", + "card_id": "w5-inspecting-and-selecting-data", + "topic": "Inspecting and Selecting Data", + "subtopic_id": "", + "subtopic_title": "", + "item_type": "key_point_detail", + "bucket": "keyPoints", + "selection_kind": "detail", + "search_text": "Summary stats\nprint(df.describe())" + }, + { + "item_id": "kp-1-d2", + "card_id": "w5-inspecting-and-selecting-data", + "topic": "Inspecting and Selecting Data", + "subtopic_id": "", + "subtopic_title": "", + "item_type": "key_point_detail", + "bucket": "keyPoints", + "selection_kind": "detail", + "search_text": "Dense reference table\nSelector | What it uses | Result\ndf.loc[row, col] | labels | endpoint-inclusive slicing\ndf.iloc[row, col] | positions | Python-style exclusive slice\ndf.head(n) | first rows | quick inspect\ndf[df['A'] > 0] | boolean filter | row subset" + }, + { + "item_id": "kp-2", + "card_id": "w5-inspecting-and-selecting-data", + "topic": "Inspecting and Selecting Data", + "subtopic_id": "w5-inspecting-and-selecting-data-core", + "subtopic_title": "head, tail, describe, loc, iloc, Result Types, and Boolean Indexing", + "item_type": "key_point", + "bucket": "keyPoints", + "selection_kind": "direct", + "search_text": "Label-based selection. Slicing with .loc is inclusive of the end name." + }, + { + "item_id": "kp-2-d1", + "card_id": "w5-inspecting-and-selecting-data", + "topic": "Inspecting and Selecting Data", + "subtopic_id": "", + "subtopic_title": "", + "item_type": "key_point_detail", + "bucket": "keyPoints", + "selection_kind": "detail", + "search_text": "Select rows/cols by name\ndf.loc['First':'Third', ['Name', 'Weight']]" + }, + { + "item_id": "kp-3", + "card_id": "w5-inspecting-and-selecting-data", + "topic": "Inspecting and Selecting Data", + "subtopic_id": "w5-inspecting-and-selecting-data-core", + "subtopic_title": "head, tail, describe, loc, iloc, Result Types, and Boolean Indexing", + "item_type": "key_point", + "bucket": "keyPoints", + "selection_kind": "direct", + "search_text": "Integer-position based selection. Slicing with .iloc is exclusive of the end index (like standard Python lists)." + }, + { + "item_id": "kp-3-d1", + "card_id": "w5-inspecting-and-selecting-data", + "topic": "Inspecting and Selecting Data", + "subtopic_id": "", + "subtopic_title": "", + "item_type": "key_point_detail", + "bucket": "keyPoints", + "selection_kind": "detail", + "search_text": "Select by position\ndf.iloc[0:2, 0:1] # Rows 0,1; Col 0" + }, + { + "item_id": "kp-4", + "card_id": "w5-inspecting-and-selecting-data", + "topic": "Inspecting and Selecting Data", + "subtopic_id": "w5-inspecting-and-selecting-data-core", + "subtopic_title": "head, tail, describe, loc, iloc, Result Types, and Boolean Indexing", + "item_type": "key_point", + "bucket": "keyPoints", + "selection_kind": "direct", + "search_text": "Selecting a single row/column with a label returns a Series; using a list/slice returns a DataFrame." + }, + { + "item_id": "kp-4-d1", + "card_id": "w5-inspecting-and-selecting-data", + "topic": "Inspecting and Selecting Data", + "subtopic_id": "", + "subtopic_title": "", + "item_type": "key_point_detail", + "bucket": "keyPoints", + "selection_kind": "detail", + "search_text": "Series vs DataFrame result\ntype(df.loc[2]) # Series\ntype(df.loc[[2]]) # DataFrame" + }, + { + "item_id": "kp-5", + "card_id": "w5-inspecting-and-selecting-data", + "topic": "Inspecting and Selecting Data", + "subtopic_id": "w5-inspecting-and-selecting-data-core", + "subtopic_title": "head, tail, describe, loc, iloc, Result Types, and Boolean Indexing", + "item_type": "key_point", + "bucket": "keyPoints", + "selection_kind": "direct", + "search_text": "Filtering data by passing a mask of True/False values (often created via comparisons)." + }, + { + "item_id": "kp-5-d1", + "card_id": "w5-inspecting-and-selecting-data", + "topic": "Inspecting and Selecting Data", + "subtopic_id": "", + "subtopic_title": "", + "item_type": "key_point_detail", + "bucket": "keyPoints", + "selection_kind": "detail", + "search_text": "Filter by condition\ndf[df['Weight'] > 60]\ndf.loc[df.Age < 155]" + }, + { + "item_id": "kp-6", + "card_id": "w5-inspecting-and-selecting-data", + "topic": "Inspecting and Selecting Data", + "subtopic_id": "w5-inspecting-and-selecting-data-core", + "subtopic_title": "head, tail, describe, loc, iloc, Result Types, and Boolean Indexing", + "item_type": "key_point", + "bucket": "keyPoints", + "selection_kind": "direct", + "search_text": "Pattern to remember: df.loc[df.index % 2 == 0, [\"B\"]]" + }, + { + "item_id": "ai-example-1", + "card_id": "w5-inspecting-and-selecting-data", + "topic": "Inspecting and Selecting Data", + "subtopic_id": "w5-inspecting-and-selecting-data-core", + "subtopic_title": "head, tail, describe, loc, iloc, Result Types, and Boolean Indexing", + "item_type": "ai_example", + "bucket": "aiExamples", + "selection_kind": "direct", + "search_text": "Summary stats\nprint(df.describe())\nUse .head(n) for the first n rows, .tail(n) for the last n rows, and .describe() for summary statistics." + }, + { + "item_id": "ai-example-2", + "card_id": "w5-inspecting-and-selecting-data", + "topic": "Inspecting and Selecting Data", + "subtopic_id": "w5-inspecting-and-selecting-data-core", + "subtopic_title": "head, tail, describe, loc, iloc, Result Types, and Boolean Indexing", + "item_type": "ai_example", + "bucket": "aiExamples", + "selection_kind": "direct", + "search_text": "Select rows/cols by name\ndf.loc['First':'Third', ['Name', 'Weight']]\nLabel-based selection. Slicing with .loc is inclusive of the end name." + }, + { + "item_id": "ai-example-3", + "card_id": "w5-inspecting-and-selecting-data", + "topic": "Inspecting and Selecting Data", + "subtopic_id": "w5-inspecting-and-selecting-data-core", + "subtopic_title": "head, tail, describe, loc, iloc, Result Types, and Boolean Indexing", + "item_type": "ai_example", + "bucket": "aiExamples", + "selection_kind": "direct", + "search_text": "Select by position\ndf.iloc[0:2, 0:1] # Rows 0,1; Col 0\nInteger-position based selection. Slicing with .iloc is exclusive of the end index (like standard Python lists)." + }, + { + "item_id": "ai-example-4", + "card_id": "w5-inspecting-and-selecting-data", + "topic": "Inspecting and Selecting Data", + "subtopic_id": "w5-inspecting-and-selecting-data-core", + "subtopic_title": "head, tail, describe, loc, iloc, Result Types, and Boolean Indexing", + "item_type": "ai_example", + "bucket": "aiExamples", + "selection_kind": "direct", + "search_text": "Series vs DataFrame result\ntype(df.loc[2]) # Series\ntype(df.loc[[2]]) # DataFrame\nSelecting a single row/column with a label returns a Series; using a list/slice returns a DataFrame." + }, + { + "item_id": "ai-example-5", + "card_id": "w5-inspecting-and-selecting-data", + "topic": "Inspecting and Selecting Data", + "subtopic_id": "w5-inspecting-and-selecting-data-core", + "subtopic_title": "head, tail, describe, loc, iloc, Result Types, and Boolean Indexing", + "item_type": "ai_example", + "bucket": "aiExamples", + "selection_kind": "direct", + "search_text": "Filter by condition\ndf[df['Weight'] > 60]\ndf.loc[df.Age < 155]\nFiltering data by passing a mask of True/False values (often created via comparisons)." + }, + { + "item_id": "ai-example-6", + "card_id": "w5-inspecting-and-selecting-data", + "topic": "Inspecting and Selecting Data", + "subtopic_id": "w5-inspecting-and-selecting-data-core", + "subtopic_title": "head, tail, describe, loc, iloc, Result Types, and Boolean Indexing", + "item_type": "ai_example", + "bucket": "aiExamples", + "selection_kind": "direct", + "search_text": "import pandas as pd\nimport pandas as pd\nd1 = [['A', 'B', 'C'],[153, 160, 150],[55, 70, 60]]\ndf1 = pd.DataFrame (d1)\ndf1 = df1.drop(1, axis = 0)\ndf1 = df1.drop(1, axis = 1)\nprint(df1)\nresult = df1.iloc[2, 2]\nprint(result)\nprint(type(result))\nDecide first whether the code is using labels (`.loc`) or integer positions (`.iloc`).\n0 2\n0 A C\n2 55 60" + }, + { + "item_id": "ai-example-7", + "card_id": "w5-inspecting-and-selecting-data", + "topic": "Inspecting and Selecting Data", + "subtopic_id": "w5-inspecting-and-selecting-data-core", + "subtopic_title": "head, tail, describe, loc, iloc, Result Types, and Boolean Indexing", + "item_type": "ai_example", + "bucket": "aiExamples", + "selection_kind": "direct", + "search_text": "import pandas as pd\nimport pandas as pd\nd1 = {10:['A', 'B', 'C', 'D'], 13:[153, 160, 150, 190], 12:[55, 70, 60, 80], 17:[10, 11, 12, 13]}\ndf1 = pd.DataFrame (d1, index=[3, 2, 1, 0])\nprint(df1)\n\nprint(df1.loc[df1.loc[:,13] < 155])\nprint(df1.loc[[3,1]])\nprint(df1.iloc[::2])\nRead the slice as `start:stop:step`; with a negative step Python walks right-to-left and still excludes the stop position." + }, + { + "item_id": "ai-example-8", + "card_id": "w5-inspecting-and-selecting-data", + "topic": "Inspecting and Selecting Data", + "subtopic_id": "w5-inspecting-and-selecting-data-core", + "subtopic_title": "head, tail, describe, loc, iloc, Result Types, and Boolean Indexing", + "item_type": "ai_example", + "bucket": "aiExamples", + "selection_kind": "direct", + "search_text": "import pandas as pd\nimport pandas as pd\nd1 = {10:['A', 'B', 'C', 'D'], 13:[153, 160, 150, 190], 12:[55, 70, 60, 80], 17:[10, 11, 12, 13]}\ndf1 = pd.DataFrame (d1, index=[3, 2, 1, 0])\nprint(df1)\n\n\nprint(df1.loc[[True, True, False, False], [False, True, False, True]])\nprint(df1.loc[[True]*2 + [False]*2, [False, True]*2])\nprint(df1.loc[[3,2], [13, 17]])\nprint(df1.iloc[:2, [1, -1]])\nUse `.loc[:, column] = ...` when the assignment should fill or update an entire column by label." + }, + { + "item_id": "exam-intro_python_sample_final_24_25-6-w4-string-operations-and-methods", + "card_id": "w5-inspecting-and-selecting-data", + "topic": "Inspecting and Selecting Data", + "subtopic_id": "", + "subtopic_title": "", + "item_type": "source_exam", + "bucket": "recommended", + "selection_kind": "source", + "search_text": "Suppose that you'd like to create a new DataFrame that contains only column 'B' for rows with indices 2, 4, and 6. Which of the following code lines will achieve what you want?\nA\nB\nC\nD\nA\nOption A uses a boolean mask on the index to find even numbers and specifies ['B'] as a list to return a DataFrame. Option D would return a Series." + }, + { + "item_id": "exam-Trial final exam Introduction to Python-6-w5-inspecting-and-selecting-data", + "card_id": "w5-inspecting-and-selecting-data", + "topic": "Inspecting and Selecting Data", + "subtopic_id": "", + "subtopic_title": "", + "item_type": "source_exam", + "bucket": "recommended", + "selection_kind": "source", + "search_text": "You have a pandas DataFrame called df that looks like this, when printed:\n\n A B C D\n1 9.1 9.5 9.0 6.0\n2 6.4 8.2 7.5 1.7\n3 2.5 5.3 8.8 3.0\n4 6.7 3.6 7.2 6.9\n5 8.4 1.9 8.2 3.3\n6 8.1 8.4 9.9 2.2\n\nSuppose that you'd like to create a new DataFrame that only contains those elements of column \"B\" in df that have an even-numbered index. Which of the following code lines will achieve what you want?\na\nb\nc\nd\na\nOption A uses boolean indexing (`df.index % 2 == 0`) to select rows with even index values, and specifically selects column \"B\" using `.loc`." + }, + { + "item_id": "ks-0114a2cff0", + "card_id": "w5-inspecting-and-selecting-data", + "topic": "Inspecting and Selecting Data", + "subtopic_id": "", + "subtopic_title": "", + "item_type": "source_lecture", + "bucket": "recommended", + "selection_kind": "source", + "search_text": "Viewing Data\nUse .head(n) for the first n rows, .tail(n) for the last n rows, and .describe() for summary statistics.\nSummary stats\nprint(df.describe())" + }, + { + "item_id": "ks-57ff66f9f1", + "card_id": "w5-inspecting-and-selecting-data", + "topic": "Inspecting and Selecting Data", + "subtopic_id": "", + "subtopic_title": "", + "item_type": "source_lecture", + "bucket": "recommended", + "selection_kind": "source", + "search_text": "Selection: loc\nLabel-based selection. Slicing with .loc is inclusive of the end name.\nSelect rows/cols by name\ndf.loc['First':'Third', ['Name', 'Weight']]" + }, + { + "item_id": "ks-dfc064979d", + "card_id": "w5-inspecting-and-selecting-data", + "topic": "Inspecting and Selecting Data", + "subtopic_id": "", + "subtopic_title": "", + "item_type": "source_lecture", + "bucket": "recommended", + "selection_kind": "source", + "search_text": "Selection: iloc\nInteger-position based selection. Slicing with .iloc is exclusive of the end index (like standard Python lists).\nSelect by position\ndf.iloc[0:2, 0:1] # Rows 0,1; Col 0" + }, + { + "item_id": "ks-99fe849762", + "card_id": "w5-inspecting-and-selecting-data", + "topic": "Inspecting and Selecting Data", + "subtopic_id": "", + "subtopic_title": "", + "item_type": "source_lecture", + "bucket": "recommended", + "selection_kind": "source", + "search_text": "Selection Result Types\nSelecting a single row/column with a label returns a Series; using a list/slice returns a DataFrame.\nSeries vs DataFrame result\ntype(df.loc[2]) # Series\ntype(df.loc[[2]]) # DataFrame" + }, + { + "item_id": "cs-3d987070d4", + "card_id": "w5-inspecting-and-selecting-data", + "topic": "Inspecting and Selecting Data", + "subtopic_id": "", + "subtopic_title": "", + "item_type": "source_notebook", + "bucket": "recommended", + "selection_kind": "source", + "search_text": "import pandas as pd\nimport pandas as pd\nd1 = [['A', 'B', 'C'],[153, 160, 150],[55, 70, 60]]\ndf1 = pd.DataFrame (d1)\ndf1 = df1.drop(1, axis = 0)\ndf1 = df1.drop(1, axis = 1)\nprint(df1)\nresult = df1.iloc[2, 2]\nprint(result)\nprint(type(result))\n0 2\n0 A C\n2 55 60" + }, + { + "item_id": "ks-f550a3ffc7", + "card_id": "w5-inspecting-and-selecting-data", + "topic": "Inspecting and Selecting Data", + "subtopic_id": "", + "subtopic_title": "", + "item_type": "source_lecture", + "bucket": "additional", + "selection_kind": "source", + "search_text": "Boolean Indexing\nFiltering data by passing a mask of True/False values (often created via comparisons).\nFilter by condition\ndf[df['Weight'] > 60]\ndf.loc[df.Age < 155]" + }, + { + "item_id": "aiq-1", + "card_id": "w5-working-with-values", + "topic": "Working With Values", + "subtopic_id": "", + "subtopic_title": "", + "item_type": "ai_common_question", + "bucket": "aiQuestions", + "selection_kind": "direct", + "search_text": "Given s = pd.Series(['abc', 'xAef']), what is the result of s.str.upper().str.count('A').mean()?\nUpper becomes ['ABC', 'XAEF']. 'A' appears once in each, so counts are [1, 1]. The mean of [1, 1] is 1.0.\nVectorized Operations" + }, + { + "item_id": "aiq-2", + "card_id": "w5-working-with-values", + "topic": "Working With Values", + "subtopic_id": "", + "subtopic_title": "", + "item_type": "ai_common_question", + "bucket": "aiQuestions", + "selection_kind": "direct", + "search_text": "If df.A has 3 elements, which operation will raise a ValueError?\nWhen broadcasting a collection to a Series, the shapes must match. (3,) and (2,) cannot be broadcast together.\nBroadcasting Errors" + }, + { + "item_id": "aiq-3", + "card_id": "w5-working-with-values", + "topic": "Working With Values", + "subtopic_id": "", + "subtopic_title": "", + "item_type": "ai_common_question", + "bucket": "aiQuestions", + "selection_kind": "direct", + "search_text": "map/filter return iterables, not lists\nlist(map(lambda x: x*2, l)) \u2014 must wrap in list(). Without it: " + }, + { + "item_id": "aiq-4", + "card_id": "w5-working-with-values", + "topic": "Working With Values", + "subtopic_id": "", + "subtopic_title": "", + "item_type": "ai_common_question", + "bucket": "aiQuestions", + "selection_kind": "direct", + "search_text": "1 + True = 2 (bool is subclass of int)\nTrue==1, False==0 in numeric contexts. type(True)==int is False but isinstance(True,int) is True" + }, + { + "item_id": "kp-1", + "card_id": "w5-working-with-values", + "topic": "Working With Values", + "subtopic_id": "w5-working-with-values-core", + "subtopic_title": "Sorting, Missing Data, Broadcasting, Vectorized Strings, isin, map, and apply", + "item_type": "key_point", + "bucket": "keyPoints", + "selection_kind": "direct", + "search_text": "Sort by labels with .sort_index() or by values with .sort_values(). axis=0 is rows, axis=1 is columns." + }, + { + "item_id": "kp-1-d1", + "card_id": "w5-working-with-values", + "topic": "Working With Values", + "subtopic_id": "", + "subtopic_title": "", + "item_type": "key_point_detail", + "bucket": "keyPoints", + "selection_kind": "detail", + "search_text": "Sorting by column values\ndf.sort_values(by='Length', ascending=False)" + }, + { + "item_id": "kp-2", + "card_id": "w5-working-with-values", + "topic": "Working With Values", + "subtopic_id": "w5-working-with-values-core", + "subtopic_title": "Sorting, Missing Data, Broadcasting, Vectorized Strings, isin, map, and apply", + "item_type": "key_point", + "bucket": "keyPoints", + "selection_kind": "direct", + "search_text": "Applying a scalar operation (like + or *) to an entire Series or DataFrame automatically." + }, + { + "item_id": "kp-2-d1", + "card_id": "w5-working-with-values", + "topic": "Working With Values", + "subtopic_id": "", + "subtopic_title": "", + "item_type": "key_point_detail", + "bucket": "keyPoints", + "selection_kind": "detail", + "search_text": "Scalar broadcasting\ndf['Height'] += 10 # Adds 10 to every cell in the column" + }, + { + "item_id": "kp-3", + "card_id": "w5-working-with-values", + "topic": "Working With Values", + "subtopic_id": "w5-working-with-values-core", + "subtopic_title": "Sorting, Missing Data, Broadcasting, Vectorized Strings, isin, map, and apply", + "item_type": "key_point", + "bucket": "keyPoints", + "selection_kind": "direct", + "search_text": "Accessible via .str, these allow string operations on every element of a Series." + }, + { + "item_id": "kp-3-d1", + "card_id": "w5-working-with-values", + "topic": "Working With Values", + "subtopic_id": "", + "subtopic_title": "", + "item_type": "key_point_detail", + "bucket": "keyPoints", + "selection_kind": "detail", + "search_text": "Chained string operations\ns.str.upper().str.count('A')" + }, + { + "item_id": "kp-4", + "card_id": "w5-working-with-values", + "topic": "Working With Values", + "subtopic_id": "w5-working-with-values-core", + "subtopic_title": "Sorting, Missing Data, Broadcasting, Vectorized Strings, isin, map, and apply", + "item_type": "key_point", + "bucket": "keyPoints", + "selection_kind": "direct", + "search_text": "A vectorized version of 'in' to check if elements are within a collection." + }, + { + "item_id": "kp-4-d1", + "card_id": "w5-working-with-values", + "topic": "Working With Values", + "subtopic_id": "", + "subtopic_title": "", + "item_type": "key_point_detail", + "bucket": "keyPoints", + "selection_kind": "detail", + "search_text": "Filtering with isin\nvowels = list('aeiou')\ns[s.str[-1].str.lower().isin(vowels)]" + }, + { + "item_id": "kp-5", + "card_id": "w5-working-with-values", + "topic": "Working With Values", + "subtopic_id": "w5-working-with-values-core", + "subtopic_title": "Sorting, Missing Data, Broadcasting, Vectorized Strings, isin, map, and apply", + "item_type": "key_point", + "bucket": "keyPoints", + "selection_kind": "direct", + "search_text": "Applies a function (often a lambda) to every element of a Series." + }, + { + "item_id": "kp-5-d1", + "card_id": "w5-working-with-values", + "topic": "Working With Values", + "subtopic_id": "", + "subtopic_title": "", + "item_type": "key_point_detail", + "bucket": "keyPoints", + "selection_kind": "detail", + "search_text": "Formatting with map\ndf['W_g'] = df['Weight'].map(lambda x: f'{x*1000} g')" + }, + { + "item_id": "kp-6", + "card_id": "w5-working-with-values", + "topic": "Working With Values", + "subtopic_id": "w5-working-with-values-core", + "subtopic_title": "Sorting, Missing Data, Broadcasting, Vectorized Strings, isin, map, and apply", + "item_type": "key_point", + "bucket": "keyPoints", + "selection_kind": "direct", + "search_text": "Applies a function along an axis (0 for columns, 1 for rows) of a DataFrame." + }, + { + "item_id": "kp-6-d1", + "card_id": "w5-working-with-values", + "topic": "Working With Values", + "subtopic_id": "", + "subtopic_title": "", + "item_type": "key_point_detail", + "bucket": "keyPoints", + "selection_kind": "detail", + "search_text": "Row-wise average\ndf['Avg'] = df.apply(lambda x: x.mean(), axis=1)" + }, + { + "item_id": "kp-7", + "card_id": "w5-working-with-values", + "topic": "Working With Values", + "subtopic_id": "w5-working-with-values-core", + "subtopic_title": "Sorting, Missing Data, Broadcasting, Vectorized Strings, isin, map, and apply", + "item_type": "key_point", + "bucket": "keyPoints", + "selection_kind": "direct", + "search_text": "Represented by np.nan. Use .isna() to detect and .fillna() to replace them." + }, + { + "item_id": "kp-7-d1", + "card_id": "w5-working-with-values", + "topic": "Working With Values", + "subtopic_id": "", + "subtopic_title": "", + "item_type": "key_point_detail", + "bucket": "keyPoints", + "selection_kind": "detail", + "search_text": "Handling NaNs\ndf.fillna('No value') # Replaces all NaNs" + }, + { + "item_id": "ai-example-1", + "card_id": "w5-working-with-values", + "topic": "Working With Values", + "subtopic_id": "w5-working-with-values-core", + "subtopic_title": "Sorting, Missing Data, Broadcasting, Vectorized Strings, isin, map, and apply", + "item_type": "ai_example", + "bucket": "aiExamples", + "selection_kind": "direct", + "search_text": "Sorting by column values\ndf.sort_values(by='Length', ascending=False)\nSort by labels with .sort_index() or by values with .sort_values(). axis=0 is rows, axis=1 is columns." + }, + { + "item_id": "ai-example-2", + "card_id": "w5-working-with-values", + "topic": "Working With Values", + "subtopic_id": "w5-working-with-values-core", + "subtopic_title": "Sorting, Missing Data, Broadcasting, Vectorized Strings, isin, map, and apply", + "item_type": "ai_example", + "bucket": "aiExamples", + "selection_kind": "direct", + "search_text": "Scalar broadcasting\ndf['Height'] += 10 # Adds 10 to every cell in the column\nApplying a scalar operation (like + or *) to an entire Series or DataFrame automatically." + }, + { + "item_id": "ai-example-3", + "card_id": "w5-working-with-values", + "topic": "Working With Values", + "subtopic_id": "w5-working-with-values-core", + "subtopic_title": "Sorting, Missing Data, Broadcasting, Vectorized Strings, isin, map, and apply", + "item_type": "ai_example", + "bucket": "aiExamples", + "selection_kind": "direct", + "search_text": "Chained string operations\ns.str.upper().str.count('A')\nAccessible via .str, these allow string operations on every element of a Series." + }, + { + "item_id": "ai-example-4", + "card_id": "w5-working-with-values", + "topic": "Working With Values", + "subtopic_id": "w5-working-with-values-core", + "subtopic_title": "Sorting, Missing Data, Broadcasting, Vectorized Strings, isin, map, and apply", + "item_type": "ai_example", + "bucket": "aiExamples", + "selection_kind": "direct", + "search_text": "Filtering with isin\nvowels = list('aeiou')\ns[s.str[-1].str.lower().isin(vowels)]\nA vectorized version of 'in' to check if elements are within a collection." + }, + { + "item_id": "ai-example-5", + "card_id": "w5-working-with-values", + "topic": "Working With Values", + "subtopic_id": "w5-working-with-values-core", + "subtopic_title": "Sorting, Missing Data, Broadcasting, Vectorized Strings, isin, map, and apply", + "item_type": "ai_example", + "bucket": "aiExamples", + "selection_kind": "direct", + "search_text": "Formatting with map\ndf['W_g'] = df['Weight'].map(lambda x: f'{x*1000} g')\nApplies a function (often a lambda) to every element of a Series." + }, + { + "item_id": "ai-example-6", + "card_id": "w5-working-with-values", + "topic": "Working With Values", + "subtopic_id": "w5-working-with-values-core", + "subtopic_title": "Sorting, Missing Data, Broadcasting, Vectorized Strings, isin, map, and apply", + "item_type": "ai_example", + "bucket": "aiExamples", + "selection_kind": "direct", + "search_text": "Row-wise average\ndf['Avg'] = df.apply(lambda x: x.mean(), axis=1)\nApplies a function along an axis (0 for columns, 1 for rows) of a DataFrame." + }, + { + "item_id": "ai-example-7", + "card_id": "w5-working-with-values", + "topic": "Working With Values", + "subtopic_id": "w5-working-with-values-core", + "subtopic_title": "Sorting, Missing Data, Broadcasting, Vectorized Strings, isin, map, and apply", + "item_type": "ai_example", + "bucket": "aiExamples", + "selection_kind": "direct", + "search_text": "Handling NaNs\ndf.fillna('No value') # Replaces all NaNs\nRepresented by np.nan. Use .isna() to detect and .fillna() to replace them." + }, + { + "item_id": "ai-example-8", + "card_id": "w5-working-with-values", + "topic": "Working With Values", + "subtopic_id": "w5-working-with-values-core", + "subtopic_title": "Sorting, Missing Data, Broadcasting, Vectorized Strings, isin, map, and apply", + "item_type": "ai_example", + "bucket": "aiExamples", + "selection_kind": "direct", + "search_text": "import pandas as pd\nimport pandas as pd\nd1 = {'A':[2, 5, 6], 'B':[3, 4, 7]}\ndf1 = pd.DataFrame (d1)\nprint(df1)\n\ndf2 = df1.loc[:]\ndf2 = df2.applymap(lambda x: 3 * x)\nprint(df2)\nUse `.loc[:, column] = ...` when the assignment should fill or update an entire column by label." + }, + { + "item_id": "manual-pandas-split-into-columns", + "card_id": "w5-working-with-values", + "topic": "Working With Values", + "subtopic_id": "w5-working-with-values-core", + "subtopic_title": "Sorting, Missing Data, Broadcasting, Vectorized Strings, isin, map, and apply", + "item_type": "ai_example", + "bucket": "aiExamples", + "selection_kind": "direct", + "search_text": "Split string data into multiple DataFrame columns\nimport pandas as pd\n\ndf = pd.DataFrame({\"place\": [\"Amsterdam; Noord-Holland\", \"Utrecht; Utrecht\"]})\ndf[[\"municipality\", \"province\"]] = df[\"place\"].str.split(\"; \", expand=True)\nprint(df)\nUse `.str.split(..., expand=True)` when the exam wants one text column unpacked into multiple DataFrame columns.\n place municipality province\n0 Amsterdam; Noord-Holland Amsterdam Noord-Holland\n1 Utrecht; Utrecht Utrecht Utrecht" + }, + { + "item_id": "manual-pandas-map-column-sum", + "card_id": "w5-working-with-values", + "topic": "Working With Values", + "subtopic_id": "w5-working-with-values-core", + "subtopic_title": "Sorting, Missing Data, Broadcasting, Vectorized Strings, isin, map, and apply", + "item_type": "ai_example", + "bucket": "aiExamples", + "selection_kind": "direct", + "search_text": "Trace `map(lambda x: x + df['B'].sum())`\nimport pandas as pd\n\ndf = pd.DataFrame({\"A\": [1, 2], \"B\": [10, 20]})\nresult = df[\"A\"].map(lambda x: x + df[\"B\"].sum())\nprint(result.tolist())\n`df[\"B\"].sum()` is computed from the whole column, so each element from `A` gets the same total from `B` added to it.\n[31, 32]" + }, + { + "item_id": "exam-intro_python_sample_final_24_25-7-w4-string-fundamentals", + "card_id": "w5-working-with-values", + "topic": "Working With Values", + "subtopic_id": "", + "subtopic_title": "", + "item_type": "source_exam", + "bucket": "recommended", + "selection_kind": "source", + "search_text": "Which of the following code lines could NOT have created df2 from df1?\nA\nB\nC\nD\nA\nOption A would sort all 5 rows of df1 and keep columns A, C, D, resulting in a 5-row DataFrame. df2 only has 3 rows (indices 4, 3, 2)." + }, + { + "item_id": "exam-intro_python_sample_final_24_25-8-w4-string-fundamentals", + "card_id": "w5-working-with-values", + "topic": "Working With Values", + "subtopic_id": "", + "subtopic_title": "", + "item_type": "source_exam", + "bucket": "recommended", + "selection_kind": "source", + "search_text": "You have a Series s with municipality and province names separated by \"; \". You'd like to create a new Series that only contains the municipality names. Which of the following code lines will achieve what you want?\nA\nB\nC\nD\nA\nThe .map() method allows applying a function (like splitting a string and taking the first part) to every element in a pandas Series." + }, + { + "item_id": "ks-305a41a33e", + "card_id": "w5-working-with-values", + "topic": "Working With Values", + "subtopic_id": "", + "subtopic_title": "", + "item_type": "source_lecture", + "bucket": "recommended", + "selection_kind": "source", + "search_text": "Sorting\nSort by labels with .sort_index() or by values with .sort_values(). axis=0 is rows, axis=1 is columns.\nSorting by column values\ndf.sort_values(by='Length', ascending=False)" + }, + { + "item_id": "ks-f8eec928e1", + "card_id": "w5-working-with-values", + "topic": "Working With Values", + "subtopic_id": "", + "subtopic_title": "", + "item_type": "source_lecture", + "bucket": "recommended", + "selection_kind": "source", + "search_text": "Broadcasting\nApplying a scalar operation (like + or *) to an entire Series or DataFrame automatically.\nScalar broadcasting\ndf['Height'] += 10 # Adds 10 to every cell in the column" + }, + { + "item_id": "ks-115ab52188", + "card_id": "w5-working-with-values", + "topic": "Working With Values", + "subtopic_id": "", + "subtopic_title": "", + "item_type": "source_lecture", + "bucket": "recommended", + "selection_kind": "source", + "search_text": "Vectorized String Methods\nAccessible via .str, these allow string operations on every element of a Series.\nChained string operations\ns.str.upper().str.count('A')" + }, + { + "item_id": "ks-2bed6c308f", + "card_id": "w5-working-with-values", + "topic": "Working With Values", + "subtopic_id": "", + "subtopic_title": "", + "item_type": "source_lecture", + "bucket": "recommended", + "selection_kind": "source", + "search_text": "isin()\nA vectorized version of 'in' to check if elements are within a collection.\nFiltering with isin\nvowels = list('aeiou')\ns[s.str[-1].str.lower().isin(vowels)]" + }, + { + "item_id": "ks-17e621a20d", + "card_id": "w5-working-with-values", + "topic": "Working With Values", + "subtopic_id": "", + "subtopic_title": "", + "item_type": "source_lecture", + "bucket": "additional", + "selection_kind": "source", + "search_text": "map()\nApplies a function (often a lambda) to every element of a Series.\nFormatting with map\ndf['W_g'] = df['Weight'].map(lambda x: f'{x*1000} g')" + }, + { + "item_id": "ks-0d2d15f8d2", + "card_id": "w5-working-with-values", + "topic": "Working With Values", + "subtopic_id": "", + "subtopic_title": "", + "item_type": "source_lecture", + "bucket": "additional", + "selection_kind": "source", + "search_text": "apply()\nApplies a function along an axis (0 for columns, 1 for rows) of a DataFrame.\nRow-wise average\ndf['Avg'] = df.apply(lambda x: x.mean(), axis=1)" + }, + { + "item_id": "ks-18a9645168", + "card_id": "w5-working-with-values", + "topic": "Working With Values", + "subtopic_id": "", + "subtopic_title": "", + "item_type": "source_lecture", + "bucket": "additional", + "selection_kind": "source", + "search_text": "Missing Data\nRepresented by np.nan. Use .isna() to detect and .fillna() to replace them.\nHandling NaNs\ndf.fillna('No value') # Replaces all NaNs" + }, + { + "item_id": "aiq-1", + "card_id": "w5-combining-data", + "topic": "Combining Data", + "subtopic_id": "", + "subtopic_title": "", + "item_type": "ai_common_question", + "bucket": "aiQuestions", + "selection_kind": "direct", + "search_text": "During a .merge(how='left') operation, what is placed in a cell if no match is found in the right DataFrame?\nPandas uses NaN (Not a Number) to represent missing data resulting from non-overlapping joins.\nMerging" + }, + { + "item_id": "kp-1", + "card_id": "w5-combining-data", + "topic": "Combining Data", + "subtopic_id": "w5-combining-data-core", + "subtopic_title": "Concatenation, Merging, and Grouping", + "item_type": "key_point", + "bucket": "keyPoints", + "selection_kind": "direct", + "search_text": "Gluing DataFrames together using pd.concat()." + }, + { + "item_id": "kp-1-d1", + "card_id": "w5-combining-data", + "topic": "Combining Data", + "subtopic_id": "", + "subtopic_title": "", + "item_type": "key_point_detail", + "bucket": "keyPoints", + "selection_kind": "detail", + "search_text": "Vertical stack\npd.concat([df1, df2], axis=0)" + }, + { + "item_id": "kp-1-d2", + "card_id": "w5-combining-data", + "topic": "Combining Data", + "subtopic_id": "", + "subtopic_title": "", + "item_type": "key_point_detail", + "bucket": "keyPoints", + "selection_kind": "detail", + "search_text": "Dense reference table\nOperation | Main axis/key idea | When useful\npd.concat([...], axis=0) | stack rows | same columns\npd.concat([...], axis=1) | add columns | aligned index\ndf.merge(...) | join on key(s) | relational combine\ndf.groupby(...) | split/apply/combine | aggregate by category" + }, + { + "item_id": "kp-2", + "card_id": "w5-combining-data", + "topic": "Combining Data", + "subtopic_id": "w5-combining-data-core", + "subtopic_title": "Concatenation, Merging, and Grouping", + "item_type": "key_point", + "bucket": "keyPoints", + "selection_kind": "direct", + "search_text": "Database-style joins using .merge(). 'how' determines the type (left, right, inner, outer)." + }, + { + "item_id": "kp-2-d1", + "card_id": "w5-combining-data", + "topic": "Combining Data", + "subtopic_id": "", + "subtopic_title": "", + "item_type": "key_point_detail", + "bucket": "keyPoints", + "selection_kind": "detail", + "search_text": "Left join on a key\ndf1.merge(df2, on='Town', how='left')" + }, + { + "item_id": "kp-3", + "card_id": "w5-combining-data", + "topic": "Combining Data", + "subtopic_id": "w5-combining-data-core", + "subtopic_title": "Concatenation, Merging, and Grouping", + "item_type": "key_point", + "bucket": "keyPoints", + "selection_kind": "direct", + "search_text": "The Split-Apply-Combine pattern using .groupby()." + }, + { + "item_id": "kp-3-d1", + "card_id": "w5-combining-data", + "topic": "Combining Data", + "subtopic_id": "", + "subtopic_title": "", + "item_type": "key_point_detail", + "bucket": "keyPoints", + "selection_kind": "detail", + "search_text": "Grouped aggregation\ndf.groupby('Nationality')['Height'].median()" + }, + { + "item_id": "ai-example-1", + "card_id": "w5-combining-data", + "topic": "Combining Data", + "subtopic_id": "w5-combining-data-core", + "subtopic_title": "Concatenation, Merging, and Grouping", + "item_type": "ai_example", + "bucket": "aiExamples", + "selection_kind": "direct", + "search_text": "Vertical stack\npd.concat([df1, df2], axis=0)\nGluing DataFrames together using pd.concat()." + }, + { + "item_id": "ai-example-2", + "card_id": "w5-combining-data", + "topic": "Combining Data", + "subtopic_id": "w5-combining-data-core", + "subtopic_title": "Concatenation, Merging, and Grouping", + "item_type": "ai_example", + "bucket": "aiExamples", + "selection_kind": "direct", + "search_text": "Left join on a key\ndf1.merge(df2, on='Town', how='left')\nDatabase-style joins using .merge(). 'how' determines the type (left, right, inner, outer)." + }, + { + "item_id": "ai-example-3", + "card_id": "w5-combining-data", + "topic": "Combining Data", + "subtopic_id": "w5-combining-data-core", + "subtopic_title": "Concatenation, Merging, and Grouping", + "item_type": "ai_example", + "bucket": "aiExamples", + "selection_kind": "direct", + "search_text": "Grouped aggregation\ndf.groupby('Nationality')['Height'].median()\nThe Split-Apply-Combine pattern using .groupby()." + }, + { + "item_id": "ai-example-4", + "card_id": "w5-combining-data", + "topic": "Combining Data", + "subtopic_id": "w5-combining-data-core", + "subtopic_title": "Concatenation, Merging, and Grouping", + "item_type": "ai_example", + "bucket": "aiExamples", + "selection_kind": "direct", + "search_text": "import pandas as pd\nimport pandas as pd\ndftax = pd.DataFrame({'Name':['A', 'B', 'C'], 'Income':[100, 200, 150], 'Tax':[10, 60, 30], 'City':['Amsterdam', 'Rotterdam', 'London']} )\n#print(dftax)\n\ndfprov = pd.DataFrame({'City':['Amsterdam', 'Rotterdam', 'Utrecht'], 'Province': ['Noord Holland', 'Zuid Holland', 'Utrecht']})\n#print(dfprov)\n\n#print(dftax.merge(dfprov, left_on='City', right_on = 'City', how='left'))\n#print(dftax.merge(dfprov, left_on='City', right_on = 'City', how='right'))\n\ndfcombined = dftax.merge(dfprov, how='left')\ndfcombined.loc[:,'Province'] = dfcombined.loc[:,'Province'].fillna('Rest')\n# We replace the missing values with a string\n# As the\u00a0groupby\u00a0method ignores\u00a0NaN\u00a0values\nresult = dfcombined.groupby('Province')['Tax'].sum()\nresult = result.sort_values(ascending = False)\n# We want the highest paying Province first\n#print(result)\n\nprint(f\"Province {result.index[0]} has the highest tax revenue: {result[0]}\")\nprint(f\"Total tax: {result.sum()}\")\nUse `.loc[:, column] = ...` when the assignment should fill or update an entire column by label.\nProvince Zuid Holland has the highest tax revenue: 60\nTotal tax: 100" + }, + { + "item_id": "ai-example-5", + "card_id": "w5-combining-data", + "topic": "Combining Data", + "subtopic_id": "w5-combining-data-core", + "subtopic_title": "Concatenation, Merging, and Grouping", + "item_type": "ai_example", + "bucket": "aiExamples", + "selection_kind": "direct", + "search_text": "import pandas as pd\nimport pandas as pd\ndftax = pd.DataFrame({'Name':['A', 'B', 'C'], 'Income':[100, 200, 150], 'Tax':[10, 60, 30], 'City':['Amsterdam', 'Rotterdam', 'London']} )\nprint(dftax)\n\ndfprov = pd.DataFrame({'City':['Amsterdam', 'Rotterdam', 'Utrecht'], 'Province': ['Noord Holland', 'Zuid Holland', 'Utrecht']})\nprint(dfprov)\n\nprint(dftax.merge(dfprov, left_on='City', right_on = 'City', how='left'))\nprint(dftax.merge(dfprov, left_on='City', right_on = 'City', how='right'))\n\ndfcombined = dftax.merge(dfprov, how='left')\ndfcombined.loc[:,'Province'] = dfcombined.loc[:,'Province'].fillna('Rest')\n# We replace the missing values in the Province column with a string\n# As the\u00a0groupby\u00a0method ignores\u00a0NaN\u00a0values\nresult = dfcombined.groupby('Province')['Tax'].sum()\nresult = result.sort_values(ascending = False)\n# We want the highest paying Province first\nprint(result)\n\nprint(result[[0]])\nprint(result.sum())\nprint(result['Noord Holland'])\nUse `.loc[:, column] = ...` when the assignment should fill or update an entire column by label." + }, + { + "item_id": "ks-591dd1aa33", + "card_id": "w5-combining-data", + "topic": "Combining Data", + "subtopic_id": "", + "subtopic_title": "", + "item_type": "source_lecture", + "bucket": "recommended", + "selection_kind": "source", + "search_text": "Concatenation\nGluing DataFrames together using pd.concat().\nVertical stack\npd.concat([df1, df2], axis=0)" + }, + { + "item_id": "ks-21496ff1cd", + "card_id": "w5-combining-data", + "topic": "Combining Data", + "subtopic_id": "", + "subtopic_title": "", + "item_type": "source_lecture", + "bucket": "recommended", + "selection_kind": "source", + "search_text": "Merging\nDatabase-style joins using .merge(). 'how' determines the type (left, right, inner, outer).\nLeft join on a key\ndf1.merge(df2, on='Town', how='left')" + }, + { + "item_id": "ks-f1be187b50", + "card_id": "w5-combining-data", + "topic": "Combining Data", + "subtopic_id": "", + "subtopic_title": "", + "item_type": "source_lecture", + "bucket": "recommended", + "selection_kind": "source", + "search_text": "Grouping\nThe Split-Apply-Combine pattern using .groupby().\nGrouped aggregation\ndf.groupby('Nationality')['Height'].median()" + }, + { + "item_id": "cs-b46633d18d", + "card_id": "w5-combining-data", + "topic": "Combining Data", + "subtopic_id": "", + "subtopic_title": "", + "item_type": "source_notebook", + "bucket": "recommended", + "selection_kind": "source", + "search_text": "import pandas as pd\nimport pandas as pd\ndftax = pd.DataFrame({'Name':['A', 'B', 'C'], 'Income':[100, 200, 150], 'Tax':[10, 60, 30], 'City':['Amsterdam', 'Rotterdam', 'London']} )\n#print(dftax)\n\ndfprov = pd.DataFrame({'City':['Amsterdam', 'Rotterdam', 'Utrecht'], 'Province': ['Noord Holland', 'Zuid Holland', 'Utrecht']})\n#print(dfprov)\n\n#print(dftax.merge(dfprov, left_on='City', right_on = 'City', how='left'))\n#print(dftax.merge(dfprov, left_on='City', right_on = 'City', how='right'))\n\ndfcombined = dftax.merge(dfprov, how='left')\ndfcombined.loc[:,'Province'] = dfcombined.loc[:,'Province'].fillna('Rest')\n# We replace the missing values with a string\n# As the\u00a0groupby\u00a0method ignores\u00a0NaN\u00a0values\nresult = dfcombined.groupby('Province')['Tax'].sum()\nresult = result.sort_values(ascending = False)\n# We want the highest paying Province first\n#print(result)\n\nprint(f\"Province {result.index[0]} has the highest tax revenue: {result[0]}\")\nprint(f\"Total tax: {result.sum()}\")\nProvince Zuid Holland has the highest tax revenue: 60\nTotal tax: 100" + }, + { + "item_id": "aiq-1", + "card_id": "w6-comprehensions", + "topic": "Comprehensions", + "subtopic_id": "", + "subtopic_title": "", + "item_type": "ai_common_question", + "bucket": "aiQuestions", + "selection_kind": "direct", + "search_text": "Why does Python interpret {x * 2 for x in l1} as a set comprehension and not a dictionary comprehension?\nDictionary comprehensions require a 'key: value' syntax within the curly braces.\nComprehensions" + }, + { + "item_id": "aiq-2", + "card_id": "w6-comprehensions", + "topic": "Comprehensions", + "subtopic_id": "", + "subtopic_title": "", + "item_type": "ai_common_question", + "bucket": "aiQuestions", + "selection_kind": "direct", + "search_text": "What is the result of {int(x) * 2 for x in '01212' if x in '02'}?\nSets only store unique values. 0*2=0 and 2*2=4. Repeated values are ignored.\nComprehensions" + }, + { + "item_id": "aiq-3", + "card_id": "w6-comprehensions", + "topic": "Comprehensions", + "subtopic_id": "", + "subtopic_title": "", + "item_type": "ai_common_question", + "bucket": "aiQuestions", + "selection_kind": "direct", + "search_text": "Slicing creates a NEW object\nl2=l1 vs l2=l1[:] \u2014 l2=l1 shares the SAME object, slicing creates independent copy" + }, + { + "item_id": "aiq-4", + "card_id": "w6-comprehensions", + "topic": "Comprehensions", + "subtopic_id": "", + "subtopic_title": "", + "item_type": "ai_common_question", + "bucket": "aiQuestions", + "selection_kind": "direct", + "search_text": "Mutable default argument\ndef f(lst=[]): \u2014 the [] is created ONCE at def time and persists across calls. Fix: use None and create inside function" + }, + { + "item_id": "kp-1", + "card_id": "w6-comprehensions", + "topic": "Comprehensions", + "subtopic_id": "w6-comprehensions-core", + "subtopic_title": "List/Dict/Set Comprehensions, Nested Variants, Logic Filters, Walrus, and enumerate Patterns", + "item_type": "key_point", + "bucket": "keyPoints", + "selection_kind": "direct", + "search_text": "Creates a set using curly braces with a single expression (not key:value pairs). Automatically handles uniqueness and ignores order." + }, + { + "item_id": "kp-1-d1", + "card_id": "w6-comprehensions", + "topic": "Comprehensions", + "subtopic_id": "", + "subtopic_title": "", + "item_type": "key_point_detail", + "bucket": "keyPoints", + "selection_kind": "detail", + "search_text": "Building a set of doubled odd numbers\ns1 = {x * 2 for x in [1, 3, 2, 5] if x % 2 != 0}" + }, + { + "item_id": "kp-2", + "card_id": "w6-comprehensions", + "topic": "Comprehensions", + "subtopic_id": "w6-comprehensions-core", + "subtopic_title": "List/Dict/Set Comprehensions, Nested Variants, Logic Filters, Walrus, and enumerate Patterns", + "item_type": "key_point", + "bucket": "keyPoints", + "selection_kind": "direct", + "search_text": "Since 'string comprehensions' don't exist natively, use a list comprehension to process characters and then '.join()' them back into a string." + }, + { + "item_id": "kp-2-d1", + "card_id": "w6-comprehensions", + "topic": "Comprehensions", + "subtopic_id": "", + "subtopic_title": "", + "item_type": "key_point_detail", + "bucket": "keyPoints", + "selection_kind": "detail", + "search_text": "Double vowels in a string\ns2 = ''.join([x*2 if x.lower() in 'aeiou' else x for x in 'Python'])" + }, + { + "item_id": "kp-3", + "card_id": "w6-comprehensions", + "topic": "Comprehensions", + "subtopic_id": "w6-comprehensions-core", + "subtopic_title": "List/Dict/Set Comprehensions, Nested Variants, Logic Filters, Walrus, and enumerate Patterns", + "item_type": "key_point", + "bucket": "keyPoints", + "selection_kind": "direct", + "search_text": "Allows creating complex nested structures like dictionaries within dictionaries in a single concise line." + }, + { + "item_id": "kp-3-d1", + "card_id": "w6-comprehensions", + "topic": "Comprehensions", + "subtopic_id": "", + "subtopic_title": "", + "item_type": "key_point_detail", + "bucket": "keyPoints", + "selection_kind": "detail", + "search_text": "Dictionary with sub-dictionaries\nresult = {x: {y: x + y for y in range(x, 4)} for x in range(1, 4)}" + }, + { + "item_id": "kp-4", + "card_id": "w6-comprehensions", + "topic": "Comprehensions", + "subtopic_id": "w6-comprehensions-core", + "subtopic_title": "List/Dict/Set Comprehensions, Nested Variants, Logic Filters, Walrus, and enumerate Patterns", + "item_type": "key_point", + "bucket": "keyPoints", + "selection_kind": "direct", + "search_text": "The walrus operator (:=) allows assigning a value to a variable within an expression, avoiding redundant calculations in filters or transformations." + }, + { + "item_id": "kp-4-d1", + "card_id": "w6-comprehensions", + "topic": "Comprehensions", + "subtopic_id": "", + "subtopic_title": "", + "item_type": "key_point_detail", + "bucket": "keyPoints", + "selection_kind": "detail", + "search_text": "Using walrus to avoid double squaring\nl1 = [(x, r) for x in range(1, 10) if 20 > (r := x**2) > 10]" + }, + { + "item_id": "kp-5", + "card_id": "w6-comprehensions", + "topic": "Comprehensions", + "subtopic_id": "w6-comprehensions-core", + "subtopic_title": "List/Dict/Set Comprehensions, Nested Variants, Logic Filters, Walrus, and enumerate Patterns", + "item_type": "key_point", + "bucket": "keyPoints", + "selection_kind": "direct", + "search_text": "Comprehensions are generally preferred over combining map() and filter() with lambda functions for readability." + }, + { + "item_id": "kp-5-d1", + "card_id": "w6-comprehensions", + "topic": "Comprehensions", + "subtopic_id": "", + "subtopic_title": "", + "item_type": "key_point_detail", + "bucket": "keyPoints", + "selection_kind": "detail", + "search_text": "Equivalent logic using map/filter\nl2 = list(map(lambda x: x*2, filter(lambda x: x%3 != 0, [1, 2, 3, 4])))" + }, + { + "item_id": "kp-6", + "card_id": "w6-comprehensions", + "topic": "Comprehensions", + "subtopic_id": "w6-comprehensions-core", + "subtopic_title": "List/Dict/Set Comprehensions, Nested Variants, Logic Filters, Walrus, and enumerate Patterns", + "item_type": "key_point", + "bucket": "keyPoints", + "selection_kind": "direct", + "search_text": "Created using parentheses (). Highly memory efficient because they calculate values on the fly rather than storing the whole list in memory." + }, + { + "item_id": "kp-6-d1", + "card_id": "w6-comprehensions", + "topic": "Comprehensions", + "subtopic_id": "", + "subtopic_title": "", + "item_type": "key_point_detail", + "bucket": "keyPoints", + "selection_kind": "detail", + "search_text": "Generator for large range\ngen = (x for x in range(1000000) if x % 3 == 0)" + }, + { + "item_id": "kp-7", + "card_id": "w6-comprehensions", + "topic": "Comprehensions", + "subtopic_id": "w6-comprehensions-core", + "subtopic_title": "List/Dict/Set Comprehensions, Nested Variants, Logic Filters, Walrus, and enumerate Patterns", + "item_type": "key_point", + "bucket": "keyPoints", + "selection_kind": "direct", + "search_text": "Can include 'if' conditions to filter keys or values during dictionary creation." + }, + { + "item_id": "kp-7-d1", + "card_id": "w6-comprehensions", + "topic": "Comprehensions", + "subtopic_id": "", + "subtopic_title": "", + "item_type": "key_point_detail", + "bucket": "keyPoints", + "selection_kind": "detail", + "search_text": "Filtering dictionary items\nd = {k: v for k, v in {'a': 1, 'b': 2}.items() if v > 1}" + }, + { + "item_id": "kp-8", + "card_id": "w6-comprehensions", + "topic": "Comprehensions", + "subtopic_id": "w6-comprehensions-core", + "subtopic_title": "List/Dict/Set Comprehensions, Nested Variants, Logic Filters, Walrus, and enumerate Patterns", + "item_type": "key_point", + "bucket": "keyPoints", + "selection_kind": "direct", + "search_text": "Use enumerate() to access both the index and the value of items within a comprehension." + }, + { + "item_id": "kp-8-d1", + "card_id": "w6-comprehensions", + "topic": "Comprehensions", + "subtopic_id": "", + "subtopic_title": "", + "item_type": "key_point_detail", + "bucket": "keyPoints", + "selection_kind": "detail", + "search_text": "Divide by index plus offset\nres = [val // (i + 6) for i, val in enumerate([46, 48])]" + }, + { + "item_id": "ai-example-1", + "card_id": "w6-comprehensions", + "topic": "Comprehensions", + "subtopic_id": "w6-comprehensions-core", + "subtopic_title": "List/Dict/Set Comprehensions, Nested Variants, Logic Filters, Walrus, and enumerate Patterns", + "item_type": "ai_example", + "bucket": "aiExamples", + "selection_kind": "direct", + "search_text": "Building a set of doubled odd numbers\ns1 = {x * 2 for x in [1, 3, 2, 5] if x % 2 != 0}\nCreates a set using curly braces with a single expression (not key:value pairs). Automatically handles uniqueness and ignores order." + }, + { + "item_id": "ai-example-2", + "card_id": "w6-comprehensions", + "topic": "Comprehensions", + "subtopic_id": "w6-comprehensions-core", + "subtopic_title": "List/Dict/Set Comprehensions, Nested Variants, Logic Filters, Walrus, and enumerate Patterns", + "item_type": "ai_example", + "bucket": "aiExamples", + "selection_kind": "direct", + "search_text": "Double vowels in a string\ns2 = ''.join([x*2 if x.lower() in 'aeiou' else x for x in 'Python'])\nSince 'string comprehensions' don't exist natively, use a list comprehension to process characters and then '.join()' them back into a string." + }, + { + "item_id": "ai-example-3", + "card_id": "w6-comprehensions", + "topic": "Comprehensions", + "subtopic_id": "w6-comprehensions-core", + "subtopic_title": "List/Dict/Set Comprehensions, Nested Variants, Logic Filters, Walrus, and enumerate Patterns", + "item_type": "ai_example", + "bucket": "aiExamples", + "selection_kind": "direct", + "search_text": "Dictionary with sub-dictionaries\nresult = {x: {y: x + y for y in range(x, 4)} for x in range(1, 4)}\nAllows creating complex nested structures like dictionaries within dictionaries in a single concise line." + }, + { + "item_id": "ai-example-4", + "card_id": "w6-comprehensions", + "topic": "Comprehensions", + "subtopic_id": "w6-comprehensions-core", + "subtopic_title": "List/Dict/Set Comprehensions, Nested Variants, Logic Filters, Walrus, and enumerate Patterns", + "item_type": "ai_example", + "bucket": "aiExamples", + "selection_kind": "direct", + "search_text": "Using walrus to avoid double squaring\nl1 = [(x, r) for x in range(1, 10) if 20 > (r := x**2) > 10]\nThe walrus operator (:=) allows assigning a value to a variable within an expression, avoiding redundant calculations in filters or transformations." + }, + { + "item_id": "ai-example-5", + "card_id": "w6-comprehensions", + "topic": "Comprehensions", + "subtopic_id": "w6-comprehensions-core", + "subtopic_title": "List/Dict/Set Comprehensions, Nested Variants, Logic Filters, Walrus, and enumerate Patterns", + "item_type": "ai_example", + "bucket": "aiExamples", + "selection_kind": "direct", + "search_text": "Equivalent logic using map/filter\nl2 = list(map(lambda x: x*2, filter(lambda x: x%3 != 0, [1, 2, 3, 4])))\nComprehensions are generally preferred over combining map() and filter() with lambda functions for readability." + }, + { + "item_id": "ai-example-6", + "card_id": "w6-comprehensions", + "topic": "Comprehensions", + "subtopic_id": "w6-comprehensions-core", + "subtopic_title": "List/Dict/Set Comprehensions, Nested Variants, Logic Filters, Walrus, and enumerate Patterns", + "item_type": "ai_example", + "bucket": "aiExamples", + "selection_kind": "direct", + "search_text": "Generator for large range\ngen = (x for x in range(1000000) if x % 3 == 0)\nCreated using parentheses (). Highly memory efficient because they calculate values on the fly rather than storing the whole list in memory." + }, + { + "item_id": "ai-example-7", + "card_id": "w6-comprehensions", + "topic": "Comprehensions", + "subtopic_id": "w6-comprehensions-core", + "subtopic_title": "List/Dict/Set Comprehensions, Nested Variants, Logic Filters, Walrus, and enumerate Patterns", + "item_type": "ai_example", + "bucket": "aiExamples", + "selection_kind": "direct", + "search_text": "Filtering dictionary items\nd = {k: v for k, v in {'a': 1, 'b': 2}.items() if v > 1}\nCan include 'if' conditions to filter keys or values during dictionary creation." + }, + { + "item_id": "ai-example-8", + "card_id": "w6-comprehensions", + "topic": "Comprehensions", + "subtopic_id": "w6-comprehensions-core", + "subtopic_title": "List/Dict/Set Comprehensions, Nested Variants, Logic Filters, Walrus, and enumerate Patterns", + "item_type": "ai_example", + "bucket": "aiExamples", + "selection_kind": "direct", + "search_text": "Divide by index plus offset\nres = [val // (i + 6) for i, val in enumerate([46, 48])]\nUse enumerate() to access both the index and the value of items within a comprehension." + }, + { + "item_id": "exam-intro_python_sample_final_24_25-12-w2-conditions", + "card_id": "w6-comprehensions", + "topic": "Comprehensions", + "subtopic_id": "", + "subtopic_title": "", + "item_type": "source_exam", + "bucket": "recommended", + "selection_kind": "source", + "search_text": "You'd like to turn every upper case letter in a list into lower case and vice versa. Which code line achieves this?\nA\nB\nC\nD\nC\nBoth options implement the conditional logic required to flip the case of each character in the list." + }, + { + "item_id": "ks-cacc4fbc21", + "card_id": "w6-comprehensions", + "topic": "Comprehensions", + "subtopic_id": "", + "subtopic_title": "", + "item_type": "source_lecture", + "bucket": "recommended", + "selection_kind": "source", + "search_text": "Set Comprehensions\nCreates a set using curly braces with a single expression (not key:value pairs). Automatically handles uniqueness and ignores order.\nBuilding a set of doubled odd numbers\ns1 = {x * 2 for x in [1, 3, 2, 5] if x % 2 != 0}" + }, + { + "item_id": "ks-0e5c8b8b42", + "card_id": "w6-comprehensions", + "topic": "Comprehensions", + "subtopic_id": "", + "subtopic_title": "", + "item_type": "source_lecture", + "bucket": "recommended", + "selection_kind": "source", + "search_text": "String Transformations via List Comprehension\nSince 'string comprehensions' don't exist natively, use a list comprehension to process characters and then '.join()' them back into a string.\nDouble vowels in a string\ns2 = ''.join([x*2 if x.lower() in 'aeiou' else x for x in 'Python'])" + }, + { + "item_id": "ks-3e04c4d5e8", + "card_id": "w6-comprehensions", + "topic": "Comprehensions", + "subtopic_id": "", + "subtopic_title": "", + "item_type": "source_lecture", + "bucket": "recommended", + "selection_kind": "source", + "search_text": "Nested Dictionary Comprehensions\nAllows creating complex nested structures like dictionaries within dictionaries in a single concise line.\nDictionary with sub-dictionaries\nresult = {x: {y: x + y for y in range(x, 4)} for x in range(1, 4)}" + }, + { + "item_id": "ks-b9d93f2bc1", + "card_id": "w6-comprehensions", + "topic": "Comprehensions", + "subtopic_id": "", + "subtopic_title": "", + "item_type": "source_lecture", + "bucket": "recommended", + "selection_kind": "source", + "search_text": "Walrus Operator in Comprehensions\nThe walrus operator (:=) allows assigning a value to a variable within an expression, avoiding redundant calculations in filters or transformations.\nUsing walrus to avoid double squaring\nl1 = [(x, r) for x in range(1, 10) if 20 > (r := x**2) > 10]" + }, + { + "item_id": "ks-1bc815f6d1", + "card_id": "w6-comprehensions", + "topic": "Comprehensions", + "subtopic_id": "", + "subtopic_title": "", + "item_type": "source_lecture", + "bucket": "additional", + "selection_kind": "source", + "search_text": "Map and Filter vs. Comprehensions\nComprehensions are generally preferred over combining map() and filter() with lambda functions for readability.\nEquivalent logic using map/filter\nl2 = list(map(lambda x: x*2, filter(lambda x: x%3 != 0, [1, 2, 3, 4])))" + }, + { + "item_id": "ks-0a4fcae36d", + "card_id": "w6-comprehensions", + "topic": "Comprehensions", + "subtopic_id": "", + "subtopic_title": "", + "item_type": "source_lecture", + "bucket": "additional", + "selection_kind": "source", + "search_text": "Generator Comprehensions\nCreated using parentheses (). Highly memory efficient because they calculate values on the fly rather than storing the whole list in memory.\nGenerator for large range\ngen = (x for x in range(1000000) if x % 3 == 0)" + }, + { + "item_id": "ks-72c58bb6b2", + "card_id": "w6-comprehensions", + "topic": "Comprehensions", + "subtopic_id": "", + "subtopic_title": "", + "item_type": "source_lecture", + "bucket": "additional", + "selection_kind": "source", + "search_text": "Dictionary Comprehensions with Logic\nCan include 'if' conditions to filter keys or values during dictionary creation.\nFiltering dictionary items\nd = {k: v for k, v in {'a': 1, 'b': 2}.items() if v > 1}" + }, + { + "item_id": "ks-dd2965ef50", + "card_id": "w6-comprehensions", + "topic": "Comprehensions", + "subtopic_id": "", + "subtopic_title": "", + "item_type": "source_lecture", + "bucket": "additional", + "selection_kind": "source", + "search_text": "Enumerate in Comprehensions\nUse enumerate() to access both the index and the value of items within a comprehension.\nDivide by index plus offset\nres = [val // (i + 6) for i, val in enumerate([46, 48])]" + }, + { + "item_id": "aiq-1", + "card_id": "w6-generators-and-iterators", + "topic": "Generators and Iterators", + "subtopic_id": "", + "subtopic_title": "", + "item_type": "ai_common_question", + "bucket": "aiQuestions", + "selection_kind": "direct", + "search_text": "What is the primary advantage of a generator over a list for large datasets?\nGenerators do not store the entire sequence in memory, which is essential for very large or infinite datasets.\nGenerators" + }, + { + "item_id": "aiq-2", + "card_id": "w6-generators-and-iterators", + "topic": "Generators and Iterators", + "subtopic_id": "", + "subtopic_title": "", + "item_type": "ai_common_question", + "bucket": "aiQuestions", + "selection_kind": "direct", + "search_text": "map/filter return iterables, not lists\nlist(map(lambda x: x*2, l)) \u2014 must wrap in list(). Without it: " + }, + { + "item_id": "kp-1", + "card_id": "w6-generators-and-iterators", + "topic": "Generators and Iterators", + "subtopic_id": "w6-generators-and-iterators-core", + "subtopic_title": "Iterator Protocol, Generator Functions, and Generator Comprehensions", + "item_type": "key_point", + "bucket": "keyPoints", + "selection_kind": "direct", + "search_text": "Functions using the 'yield' keyword. They produce values one at a time and maintain their local state (variables) between calls." + }, + { + "item_id": "kp-1-d1", + "card_id": "w6-generators-and-iterators", + "topic": "Generators and Iterators", + "subtopic_id": "", + "subtopic_title": "", + "item_type": "key_point_detail", + "bucket": "keyPoints", + "selection_kind": "detail", + "search_text": "Simple step generator\ndef count(start, stop, step):\n while start <= stop:\n yield start\n start += step" + }, + { + "item_id": "kp-2", + "card_id": "w6-generators-and-iterators", + "topic": "Generators and Iterators", + "subtopic_id": "w6-generators-and-iterators-core", + "subtopic_title": "Iterator Protocol, Generator Functions, and Generator Comprehensions", + "item_type": "key_point", + "bucket": "keyPoints", + "selection_kind": "direct", + "search_text": "Objects that can be traversed using next(). Lists can be turned into iterators using iter(). They raise StopIteration when exhausted." + }, + { + "item_id": "kp-2-d1", + "card_id": "w6-generators-and-iterators", + "topic": "Generators and Iterators", + "subtopic_id": "", + "subtopic_title": "", + "item_type": "key_point_detail", + "bucket": "keyPoints", + "selection_kind": "detail", + "search_text": "Manual iteration\nit = iter([1, 2]); print(next(it)); print(next(it))" + }, + { + "item_id": "ai-example-1", + "card_id": "w6-generators-and-iterators", + "topic": "Generators and Iterators", + "subtopic_id": "w6-generators-and-iterators-core", + "subtopic_title": "Iterator Protocol, Generator Functions, and Generator Comprehensions", + "item_type": "ai_example", + "bucket": "aiExamples", + "selection_kind": "direct", + "search_text": "Simple step generator\ndef count(start, stop, step):\n while start <= stop:\n yield start\n start += step\nFunctions using the 'yield' keyword. They produce values one at a time and maintain their local state (variables) between calls." + }, + { + "item_id": "ai-example-2", + "card_id": "w6-generators-and-iterators", + "topic": "Generators and Iterators", + "subtopic_id": "w6-generators-and-iterators-core", + "subtopic_title": "Iterator Protocol, Generator Functions, and Generator Comprehensions", + "item_type": "ai_example", + "bucket": "aiExamples", + "selection_kind": "direct", + "search_text": "Manual iteration\nit = iter([1, 2]); print(next(it)); print(next(it))\nObjects that can be traversed using next(). Lists can be turned into iterators using iter(). They raise StopIteration when exhausted." + }, + { + "item_id": "ai-example-3", + "card_id": "w6-generators-and-iterators", + "topic": "Generators and Iterators", + "subtopic_id": "w6-generators-and-iterators-core", + "subtopic_title": "Iterator Protocol, Generator Functions, and Generator Comprehensions", + "item_type": "ai_example", + "bucket": "aiExamples", + "selection_kind": "direct", + "search_text": "myiterator = iter([1,3,5])\nmyiterator = iter([1,3,5])\n\nprint(next(myiterator))\nprint(next(myiterator))\nprint(next(myiterator))\nprint(next(myiterator))" + }, + { + "item_id": "ai-example-4", + "card_id": "w6-generators-and-iterators", + "topic": "Generators and Iterators", + "subtopic_id": "w6-generators-and-iterators-core", + "subtopic_title": "Iterator Protocol, Generator Functions, and Generator Comprehensions", + "item_type": "ai_example", + "bucket": "aiExamples", + "selection_kind": "direct", + "search_text": "class Mylist(list):\nclass Mylist(list):\n pass\nmyiterator = iter(Mylist([1,3,5]))\n\nprint(next(myiterator))\nprint(next(myiterator))\nprint(next(myiterator))\nprint(next(myiterator))" + }, + { + "item_id": "ai-example-5", + "card_id": "w6-generators-and-iterators", + "topic": "Generators and Iterators", + "subtopic_id": "w6-generators-and-iterators-core", + "subtopic_title": "Iterator Protocol, Generator Functions, and Generator Comprehensions", + "item_type": "ai_example", + "bucket": "aiExamples", + "selection_kind": "direct", + "search_text": "mygenerator = (x for x in range(100000000) if x%3 == 0 or x%4 == 0)\nmygenerator = (x for x in range(100000000) if x%3 == 0 or x%4 == 0)\nprint(next(mygenerator))\nprint(next(mygenerator))\nprint(next(mygenerator))\nprint(next(mygenerator))\nExpand `range(start, stop, step)` manually; `stop` is excluded and the next value is found by adding `step` each time." + }, + { + "item_id": "ai-example-6", + "card_id": "w6-generators-and-iterators", + "topic": "Generators and Iterators", + "subtopic_id": "w6-generators-and-iterators-core", + "subtopic_title": "Iterator Protocol, Generator Functions, and Generator Comprehensions", + "item_type": "ai_example", + "bucket": "aiExamples", + "selection_kind": "direct", + "search_text": "class Mylist(list):\nclass Mylist(list):\n def __iter__ (self):\n pass\nmyiterator = iter(Mylist([1,3,5]))\n\nprint(next(myiterator))\nprint(next(myiterator))\nprint(next(myiterator))\nprint(next(myiterator))" + }, + { + "item_id": "ai-example-7", + "card_id": "w6-generators-and-iterators", + "topic": "Generators and Iterators", + "subtopic_id": "w6-generators-and-iterators-core", + "subtopic_title": "Iterator Protocol, Generator Functions, and Generator Comprehensions", + "item_type": "ai_example", + "bucket": "aiExamples", + "selection_kind": "direct", + "search_text": "def generatorfunction(start, stop, step):\ndef generatorfunction(start, stop, step):\n while (num:=start) <= stop:\n yield num\n start += step\n return 'End of numbers'\nfor x in generatorfunction(1, 5, 2):\n print(x)\nFor numeric variables, `a += 1` updates the stored value the same way as `a = a + 1`." + }, + { + "item_id": "ai-example-8", + "card_id": "w6-generators-and-iterators", + "topic": "Generators and Iterators", + "subtopic_id": "w6-generators-and-iterators-core", + "subtopic_title": "Iterator Protocol, Generator Functions, and Generator Comprehensions", + "item_type": "ai_example", + "bucket": "aiExamples", + "selection_kind": "direct", + "search_text": "def generatorfunction(start, stop, step):\ndef generatorfunction(start, stop, step):\n while True:\n num = start\n start += step\n if num <= stop:\n yield num\n else:\n return 'End of numbers'\nprint(list(generatorfunction(1, 5, 2)))\nFor numeric variables, `a += 1` updates the stored value the same way as `a = a + 1`." + }, + { + "item_id": "ks-900b394f8e", + "card_id": "w6-generators-and-iterators", + "topic": "Generators and Iterators", + "subtopic_id": "", + "subtopic_title": "", + "item_type": "source_lecture", + "bucket": "recommended", + "selection_kind": "source", + "search_text": "Generator Functions\nFunctions using the 'yield' keyword. They produce values one at a time and maintain their local state (variables) between calls.\nSimple step generator\ndef count(start, stop, step):\n while start <= stop:\n yield start\n start += step" + }, + { + "item_id": "ks-cd030b9520", + "card_id": "w6-generators-and-iterators", + "topic": "Generators and Iterators", + "subtopic_id": "", + "subtopic_title": "", + "item_type": "source_lecture", + "bucket": "recommended", + "selection_kind": "source", + "search_text": "Iterators\nObjects that can be traversed using next(). Lists can be turned into iterators using iter(). They raise StopIteration when exhausted.\nManual iteration\nit = iter([1, 2]); print(next(it)); print(next(it))" + }, + { + "item_id": "manual-strftime-vs-strptime", + "card_id": "w6-datetime", + "topic": "Datetime", + "subtopic_id": "", + "subtopic_title": "", + "item_type": "ai_common_question", + "bucket": "aiQuestions", + "selection_kind": "direct", + "search_text": "When do you use `strftime` versus `strptime`?\n`strftime` formats a datetime into text; `strptime` parses text into a datetime object.\ndt.strftime('%Y-%m-%d')\ndatetime.strptime('2024-05-20', '%Y-%m-%d')" + }, + { + "item_id": "manual-timedelta-attrs", + "card_id": "w6-datetime", + "topic": "Datetime", + "subtopic_id": "", + "subtopic_title": "", + "item_type": "ai_common_question", + "bucket": "aiQuestions", + "selection_kind": "direct", + "search_text": "Which attributes exist directly on a `timedelta` object?\nA `timedelta` stores `days`, `seconds`, and `microseconds`; hours or weeks must be derived or supplied when constructing it.\ndelta = end - start\nprint(delta.days, delta.seconds)" + }, + { + "item_id": "manual-day-of-year", + "card_id": "w6-datetime", + "topic": "Datetime", + "subtopic_id": "", + "subtopic_title": "", + "item_type": "ai_common_question", + "bucket": "aiQuestions", + "selection_kind": "direct", + "search_text": "How can you compute the day number within the year from a datetime?\nSubtract January 1st of the same year, take `.days`, and add 1 so January 1st becomes day 1.\ndef day_of_year(dt):\n return (dt - datetime(dt.year, 1, 1)).days + 1" + }, + { + "item_id": "kp-manual-datetime-now", + "card_id": "w6-datetime", + "topic": "Datetime", + "subtopic_id": "", + "subtopic_title": "", + "item_type": "key_point", + "bucket": "keyPoints", + "selection_kind": "direct", + "search_text": "`datetime.now()` gives the current local datetime; use `.timestamp()` only when you specifically need seconds since the Unix epoch." + }, + { + "item_id": "kp-manual-datetime-format", + "card_id": "w6-datetime", + "topic": "Datetime", + "subtopic_id": "", + "subtopic_title": "", + "item_type": "key_point", + "bucket": "keyPoints", + "selection_kind": "direct", + "search_text": "`strftime` formats a datetime into text; `strptime` parses text into a datetime object." + }, + { + "item_id": "kp-manual-datetime-delta", + "card_id": "w6-datetime", + "topic": "Datetime", + "subtopic_id": "", + "subtopic_title": "", + "item_type": "key_point", + "bucket": "keyPoints", + "selection_kind": "direct", + "search_text": "Subtracting two datetimes gives a `timedelta`; its most-used direct attributes are `.days`, `.seconds`, and `.microseconds`." + }, + { + "item_id": "kp-manual-datetime-replace", + "card_id": "w6-datetime", + "topic": "Datetime", + "subtopic_id": "", + "subtopic_title": "", + "item_type": "key_point", + "bucket": "keyPoints", + "selection_kind": "direct", + "search_text": "Datetime objects are immutable, so `.replace(...)` returns a new datetime instead of modifying the original one." + }, + { + "item_id": "manual-datetime-format", + "card_id": "w6-datetime", + "topic": "Datetime", + "subtopic_id": "w6-datetime-core", + "subtopic_title": "now, Timestamps, strftime, strptime, timedelta, and Date Arithmetic", + "item_type": "ai_example", + "bucket": "aiExamples", + "selection_kind": "direct", + "search_text": "Format a datetime with `strftime`\nfrom datetime import datetime\n\ndt = datetime(2024, 5, 20, 14, 30)\nprint(dt.strftime('%Y-%m-%d %H:%M'))\nUse `strftime` when the exam asks for a formatted string such as year-month-day or hour-minute.\n2024-05-20 14:30" + }, + { + "item_id": "manual-datetime-parse", + "card_id": "w6-datetime", + "topic": "Datetime", + "subtopic_id": "w6-datetime-core", + "subtopic_title": "now, Timestamps, strftime, strptime, timedelta, and Date Arithmetic", + "item_type": "ai_example", + "bucket": "aiExamples", + "selection_kind": "direct", + "search_text": "Parse text with `strptime`\nfrom datetime import datetime\n\ndt = datetime.strptime('2024-05-20', '%Y-%m-%d')\nprint(dt)\nThe format string must match the input text exactly, including separators.\n2024-05-20 00:00:00" + }, + { + "item_id": "manual-datetime-delta", + "card_id": "w6-datetime", + "topic": "Datetime", + "subtopic_id": "w6-datetime-core", + "subtopic_title": "now, Timestamps, strftime, strptime, timedelta, and Date Arithmetic", + "item_type": "ai_example", + "bucket": "aiExamples", + "selection_kind": "direct", + "search_text": "Subtract datetimes to get a `timedelta`\nfrom datetime import datetime\n\nstart = datetime(2024, 1, 1)\nend = datetime(2024, 1, 4)\nprint((end - start).days)\nDatetime subtraction gives a `timedelta`, whose `.days` attribute is often what exam questions want.\n3" + }, + { + "item_id": "manual-datetime-replace", + "card_id": "w6-datetime", + "topic": "Datetime", + "subtopic_id": "w6-datetime-core", + "subtopic_title": "now, Timestamps, strftime, strptime, timedelta, and Date Arithmetic", + "item_type": "ai_example", + "bucket": "aiExamples", + "selection_kind": "direct", + "search_text": "`.replace(...)` returns a new datetime\nfrom datetime import datetime\n\nd = datetime(2024, 5, 20)\nprint(d.replace(year=2026))\nprint(d)\nDatetime objects are immutable, so `.replace(...)` does not modify the original object in place.\n2026-05-20 00:00:00\n2024-05-20 00:00:00" + }, + { + "item_id": "manual-datetime-overlap", + "card_id": "w6-datetime", + "topic": "Datetime", + "subtopic_id": "w6-datetime-core", + "subtopic_title": "now, Timestamps, strftime, strptime, timedelta, and Date Arithmetic", + "item_type": "ai_example", + "bucket": "aiExamples", + "selection_kind": "direct", + "search_text": "Check whether two datetime intervals overlap\nfrom datetime import datetime\n\nstart_a = datetime(2024, 5, 20, 9, 0)\nend_a = datetime(2024, 5, 20, 11, 0)\nstart_b = datetime(2024, 5, 20, 10, 30)\nend_b = datetime(2024, 5, 20, 12, 0)\n\noverlaps = max(start_a, start_b) < min(end_a, end_b)\nprint(overlaps)\nA reliable overlap check compares the later start with the earlier end; there is overlap only when the later start is still before the earlier end.\nTrue" + }, + { + "item_id": "manual-datetime-strftime-loop", + "card_id": "w6-datetime", + "topic": "Datetime", + "subtopic_id": "w6-datetime-core", + "subtopic_title": "now, Timestamps, strftime, strptime, timedelta, and Date Arithmetic", + "item_type": "ai_example", + "bucket": "aiExamples", + "selection_kind": "direct", + "search_text": "Do datetime math before `strftime` turns values into strings\nfrom datetime import datetime, timedelta\n\nday = datetime(2024, 1, 1)\nlabels = []\nfor _ in range(3):\n labels.append(day.strftime(\"%Y-%m-%d\"))\n day += timedelta(days=1)\nprint(labels)\nAfter `strftime`, the value is plain text, so increment the datetime object first and only store formatted strings as the final display step.\n['2024-01-01', '2024-01-02', '2024-01-03']" + }, + { + "item_id": "exam-intro_python_sample_final_24_25-9-w6-datetime", + "card_id": "w6-datetime", + "topic": "Datetime", + "subtopic_id": "", + "subtopic_title": "", + "item_type": "source_exam", + "bucket": "recommended", + "selection_kind": "source", + "search_text": "Suppose that you call the function like this: get_months([\"03/02/2013\", \"03.02.2013\", \"03-02-2013\"]). What does the function call return?\nA\nB\nC\nD\nA\n1st string: contains '/' so it uses %m/%d/%Y -> month 3. 2nd: contains neither '-' nor '/' -> None. 3rd: contains '-' so it uses %d-%m-%Y -> month 2." + }, + { + "item_id": "exam-intro_python_sample_final_24_25-10-w6-datetime", + "card_id": "w6-datetime", + "topic": "Datetime", + "subtopic_id": "", + "subtopic_title": "", + "item_type": "source_exam", + "bucket": "recommended", + "selection_kind": "source", + "search_text": "Which of the following code segments will return the number of the day (1-366) that a datetime value represents within the year?\nA\nB\nC\nD\nA\nSubtracting two datetime objects results in a timedelta object. Accessing the .days attribute gives the difference as an integer. Adding 1 makes it 1-based (Jan 1st = day 1)." + }, + { + "item_id": "ks-e643ee5e77", + "card_id": "w6-datetime", + "topic": "Datetime", + "subtopic_id": "", + "subtopic_title": "", + "item_type": "source_lecture", + "bucket": "recommended", + "selection_kind": "source", + "search_text": "datetime.now and Timestamps\ndatetime.now() retrieves the current local time. timestamp() returns the seconds since the Unix Epoch (Jan 1, 1970).\nGetting current timestamp\nfrom datetime import datetime\nprint(datetime.now().timestamp())" + }, + { + "item_id": "ks-755c23c4be", + "card_id": "w6-datetime", + "topic": "Datetime", + "subtopic_id": "", + "subtopic_title": "", + "item_type": "source_lecture", + "bucket": "recommended", + "selection_kind": "source", + "search_text": "strftime: Date to String\nFormats a datetime object into a readable string using format codes (e.g., %Y for 4-digit year, %m for month).\nFormatting a date\nfrom datetime import datetime\nprint(datetime.now().strftime('%Y-%m-%d %H:%M'))" + }, + { + "item_id": "ks-169cc25be1", + "card_id": "w6-datetime", + "topic": "Datetime", + "subtopic_id": "", + "subtopic_title": "", + "item_type": "source_lecture", + "bucket": "recommended", + "selection_kind": "source", + "search_text": "strptime: String to Date\nParses a string into a datetime object based on a provided format template.\nParsing a date string\nfrom datetime import datetime\nd = datetime.strptime('2024-05-20', '%Y-%m-%d')" + }, + { + "item_id": "ks-86cd7ede1c", + "card_id": "w6-datetime", + "topic": "Datetime", + "subtopic_id": "", + "subtopic_title": "", + "item_type": "source_lecture", + "bucket": "recommended", + "selection_kind": "source", + "search_text": "Timedelta and Date Arithmetic\nTimedelta objects represent durations. Subtracting two datetimes creates a timedelta; adding a timedelta to a datetime shifts the date.\nCalculating days difference\nfrom datetime import datetime, timedelta\ndiff = datetime(2024, 1, 1) - datetime(2023, 1, 1)\nprint(diff.days)" + }, + { + "item_id": "cs-905c77e1f3", + "card_id": "w6-datetime", + "topic": "Datetime", + "subtopic_id": "", + "subtopic_title": "", + "item_type": "source_notebook", + "bucket": "recommended", + "selection_kind": "source", + "search_text": "from datetime import datetime\nfrom datetime import datetime\nd = datetime.strptime(\"2024$05%20\",\"%Y$%m%%%d\")\nprint(d)\n\nfrom datetime import datetime\nd = datetime.strptime(\"24$05%20\",\"%y$%m%%%d\")\nprint(d)\n\nfrom datetime import datetime\nd = datetime.strptime(\"24$05%20\",\"%y$%m%%%d\")\nprint(d)\n\nfrom datetime import datetime\nd = datetime.strptime(\"2024*141\",\"%Y*%j\")\nprint(d)\n\nfrom datetime import datetime\nd = datetime.strptime(\"2024*20xyz1\",\"%Y*%Uxyz%w\")\nprint(d)\n\nfrom datetime import datetime\nd = datetime.strptime(\"202420Monday\",\"%Y%U%A\")\nprint(d)\n\nfrom datetime import datetime\nd = datetime.strptime(\"00:00:00 20-05-2024\", \"%H:%M:%S %d-%m-%Y\")\nprint(d)\n2024-05-20 00:00:00\n2024-05-20 00:00:00\n2024-05-20 00:00:00\n2024-05-20 00:00:00\n2024-05-20 00:00:00\n2024-05-20 00:00:00\n2024-05-20 00:00:00" + }, + { + "item_id": "ks-662456da41", + "card_id": "w6-datetime", + "topic": "Datetime", + "subtopic_id": "", + "subtopic_title": "", + "item_type": "source_lecture", + "bucket": "additional", + "selection_kind": "source", + "search_text": "The replace() Method\nDatetime objects are immutable. The replace() method creates a new datetime object with specific attributes changed.\nChanging the year of a date\nfrom datetime import datetime\nd = datetime.now().replace(year=2026)" + } +] \ No newline at end of file diff --git a/topic_cards.json b/topic_cards.json index bee76c3..e2050dc 100644 --- a/topic_cards.json +++ b/topic_cards.json @@ -1,23 +1,4 @@ { - "meta": { - "generated_from": "data/study_db.json", - "generator": "build_topic_cards.py", - "course": "Introduction to Python", - "weeks_covered": [ - 1, - 2, - 3, - 4, - 5, - 6 - ], - "total_cards": 27, - "notes": [ - "Cards are materialized directly from the lecture-first canonical study database.", - "Each card maps to one sidebar topic, with subtopics rendered inside the topic detail page.", - "AI-style summary, examples, and key points are deterministic curated fallbacks until optional enrichment scripts overwrite them." - ] - }, "cards": [ { "id": "w1-python-basics", @@ -404,105 +385,13 @@ "cs-7498cfc507", "cs-de6e934319", "cs-267155ddae" - ] + ], + "homework_snippets": [], + "homework_recommended_ids": [] } }, { - "id": "w1-objects-and-names", - "topic": "Objects and Names", "canonical_topic": "w1-objects-and-names", - "weeks": [ - 1 - ], - "week_id": "week-1", - "topic_meta": { - "week": 1, - "week_id": "week-1", - "week_title": "Week 1", - "topic_id": "w1-objects-and-names", - "topic_title": "Objects and Names", - "topic_order": 2 - }, - "subtopics": [ - { - "id": "w1-objects-and-names-core", - "title": "Objects, Types, Mutability, Assignment, and Names", - "order": 1, - "summary": "Objects have identity, type, and value. Names bind to objects; rebinding changes the name, while mutation only matters for mutable objects.", - "item_ids": { - "lecture_snippet_ids": [ - "ks-e88d0a8060", - "ks-eae9bf47dd", - "ks-61c5deec4a", - "ks-cb3a9e3fd2", - "ks-d79a1899f6", - "ks-6f41148083", - "ks-0153de2f70", - "ks-df3b849d59", - "ks-419e787b39" - ], - "exam_question_ids": [ - "exam-trial_midterm-1-w1-objects-and-names", - "exam-trial_midterm-3-w1-objects-and-names", - "exam-trial_midterm-4-w1-objects-and-names", - "exam-trial_midterm-7-w1-objects-and-names", - "exam-trial_midterm-9-w1-objects-and-names", - "exam-trial_midterm-11-w1-objects-and-names", - "exam-trial_midterm-12-w1-objects-and-names", - "exam-trial_midterm-14-w1-objects-and-names", - "exam-trial_midterm-15-w1-objects-and-names", - "exam-trial_midterm-16-w1-objects-and-names", - "exam-trial_midterm-18-w1-objects-and-names", - "exam-trial_midterm-20-w1-objects-and-names", - "exam-trial_midterm-21-w1-objects-and-names", - "exam-trial_midterm-22-w1-objects-and-names", - "exam-trial_midterm-24-w1-objects-and-names", - "exam-midterm_2023-4-w1-objects-and-names", - "exam-midterm_2024-4-w1-objects-and-names", - "exam-midterm_2024-6-w1-objects-and-names", - "exam-extra_practice-11-w1-objects-and-names", - "exam-Trial final - Introduction to Python - 22/23-1-w1-objects-and-names", - "exam-trial-final-exam-py22-1-w1-objects-and-names", - "exam-Test Resit - Introduction to Python - 22/23-3-w1-objects-and-names", - "exam-intro_python_sample_final_24_25-13-w1-objects-and-names", - "exam-Trial final exam Introduction to Python-3-w1-objects-and-names" - ], - "notebook_snippet_ids": [ - "cs-cd4f0b5c6e", - "cs-b65f3408e3", - "cs-d185f0c824", - "cs-04169579a8", - "cs-58c37dfe80", - "cs-ef4e6233fe", - "cs-94491b4b00", - "cs-33e88a778b" - ], - "example_ids": [ - "ai-example-1", - "ai-example-2", - "ai-example-3", - "ai-example-4", - "ai-example-5", - "ai-example-6", - "ai-example-7", - "ai-example-8", - "manual-objects-aliasing" - ], - "key_point_ids": [ - "kp-1", - "kp-2", - "kp-3", - "kp-4", - "kp-5", - "kp-6", - "kp-manual-aliasing-copy", - "kp-7", - "kp-8", - "kp-9" - ] - } - } - ], "exam_stats": { "total_hits": 24, "by_exam": { @@ -518,274 +407,192 @@ }, "coverage_count": 9 }, + "id": "w1-objects-and-names", "related_topics": [ "Objects, Types, Mutability, Assignment, and Names" ], - "trap_patterns": [ - { - "pattern": "Slicing creates a NEW object", - "trap": "l2=l1 vs l2=l1[:] — l2=l1 shares the SAME object, slicing creates independent copy", - "weeks": [ - 1 - ], - "appears_in_exams": [ - "trial_midterm", - "midterm_2023", - "midterm_2024", - "extra_practice" - ] - }, - { - "pattern": "Mutable default argument", - "trap": "def f(lst=[]): — the [] is created ONCE at def time and persists across calls. Fix: use None and create inside function", - "weeks": [ - 3 - ], - "appears_in_exams": [ - "trial_midterm", - "midterm_2024" - ] - }, - { - "pattern": "Mutable parameter sharing", - "trap": "When mutable object passed as argument, parameter and argument point to SAME object — mutations inside function affect original", - "weeks": [ - 3 - ], - "appears_in_exams": [ - "midterm_2023", - "extra_practice" - ] - }, - { - "pattern": "UnboundLocalError", - "trap": "If a name appears on the left side of assignment ANYWHERE in a function, Python treats it as local THROUGHOUT the function body — even before the assignment line", - "weeks": [ - 3 - ], - "appears_in_exams": [ - "trial_midterm", - "extra_practice" - ] - }, - { - "pattern": "Tuple inside mutable container can be mutated via the mutable part", - "trap": "t=(1,[2,3],4); t[1].append(5) works — tuple immutable means you can't reassign t[1], but the list t[1] refers to IS mutable", - "weeks": [ - 1 + "sections": { + "ai_common_questions": { + "status": "curated", + "bullets": [ + "Assume you already have a variable called x, which contains a list of integers.\nWhich of the following programs will print you a list of the squared values of the elements in x?", + "Suppose you have the following function:\ndef multiply(*args, factor=2):\ntotal = 1\nfor num in args:\ntotal *= num\nreturn total * factor\nWhich of the following functions will return the same values as the function above, if we call the function thrice as follows…", + "Assume you have the following variables:\nx = 3\ny = 3.0\nz = '3'\nWhat will be printed by the following code:\nprint((x != z and x == int(z)) or (x != y and y != z))\nA 3\nB The code will result in an error.\nC False\nD True", + "You need to write a function called dict_keys that checks whether a certain key is in available in a certain dictionary.", + "l2=l1 vs l2=l1[:] — l2=l1 shares the SAME object, slicing creates independent copy", + "def f(lst=[]): — the [] is created ONCE at def time and persists across calls. Fix: use None and create inside function" ], - "appears_in_exams": [ - "midterm_2024" - ] - }, - { - "pattern": "Wrong bracket type errors", - "trap": "print[1] → TypeError 'not subscriptable'; l1(1) → TypeError 'not callable'", - "weeks": [ - 3 + "items": [ + { + "id": "aiq-1", + "summary": "Which of the following statements is correct? I: Two objects can have different values, while having the same type. II: Two objects can have the same value, while having different types.", + "detail": "I is correct (e.g. a=1, b=2, both int). II is incorrect — if two objects have the same value they must have the same type.", + "extra": "Objects/types", + "subtopic_id": "w1-objects-and-names-core", + "subtopic_title": "Objects, Types, Mutability, Assignment, and Names" + }, + { + "id": "aiq-2", + "summary": "Why does the following code work even though strings are immutable?", + "detail": "Decide whether the code is rebinding a name or mutating a shared mutable object.", + "extra": "Immutability/names", + "subtopic_id": "w1-objects-and-names-core", + "subtopic_title": "Objects, Types, Mutability, Assignment, and Names" + }, + { + "id": "aiq-3", + "summary": "Assume you already have a variable called x, which contains a list of integers.", + "detail": "Expand `range(start, stop, step)` manually; `stop` is excluded and the next value is found by adding `step` each time.", + "extra": "Exam • trial_midterm • Q1", + "subtopic_id": "w1-objects-and-names-core", + "subtopic_title": "Objects, Types, Mutability, Assignment, and Names", + "code": "For example:\nIf x = [1, 2, 4, 8]\nthe program should prints:\n[1, 4, 16, 64].\nA mylist = []\nfor i in x:\nmylist[i] = x[i]**2\nprint(mylist)\nB mylist = [0] * len(x)\nfor i in range(len(x)):\nmylist[i] = x[i]**2\nprint(mylist)" + }, + { + "id": "aiq-4", + "summary": "Suppose you have the following function:", + "detail": "Trace the returned value, not just what gets printed while the function runs.", + "extra": "Exam • trial_midterm • Q3", + "subtopic_id": "w1-objects-and-names-core", + "subtopic_title": "Objects, Types, Mutability, Assignment, and Names", + "code": "Suppose you have the following function:\ndef multiply(*args, factor=2):\ntotal = 1\nfor num in args:\ntotal *= num\nreturn total * factor\nWhich of the following functions will return the same values as the function above, if we call the function thrice as follows:\nmultiply(1, 2, factor=3)\nmultiply(3, 4)\nmultiply()\nA def multiply(*args, factor=2):\ntotal = args[0]" + }, + { + "id": "aiq-5", + "summary": "Assume you have the following variables:", + "detail": "Decide whether the code is rebinding a name or mutating a shared mutable object.", + "extra": "Exam • trial_midterm • Q4", + "subtopic_id": "w1-objects-and-names-core", + "subtopic_title": "Objects, Types, Mutability, Assignment, and Names", + "code": "Assume you have the following variables:\nx = 3\ny = 3.0\nz = '3'\nWhat will be printed by the following code:\nprint((x != z and x == int(z)) or (x != y and y != z))\nA 3\nB The code will result in an error.\nC False\nD True" + }, + { + "id": "aiq-6", + "summary": "Slicing creates a NEW object", + "detail": "l2=l1 vs l2=l1[:] — l2=l1 shares the SAME object, slicing creates independent copy", + "extra": "", + "subtopic_id": "", + "subtopic_title": "" + }, + { + "id": "aiq-7", + "summary": "Mutable default argument", + "detail": "def f(lst=[]): — the [] is created ONCE at def time and persists across calls. Fix: use None and create inside function", + "extra": "", + "subtopic_id": "", + "subtopic_title": "" + } ], - "appears_in_exams": [ - "trial_midterm" - ] + "generator": "lecture-first-build", + "model": null }, - { - "pattern": "map/filter return iterables, not lists", - "trap": "list(map(lambda x: x*2, l)) — must wrap in list(). Without it: ", - "weeks": [ - 3 - ], - "appears_in_exams": [ - "trial_midterm", - "extra_practice" - ] - }, - { - "pattern": "1 + True = 2 (bool is subclass of int)", - "trap": "True==1, False==0 in numeric contexts. type(True)==int is False but isinstance(True,int) is True", - "weeks": [ - 2 - ], - "appears_in_exams": [ - "midterm_2023" - ] - } - ], - "sections": { - "lecture_snippets": [ + "ai_examples": [ { - "id": "ks-e88d0a8060", - "week": 1, - "source": "materials/lectures/Lecture Week 1.md", - "source_type": "lecture", - "topic": "Objects and Names", + "id": "ai-example-1", + "kind": "correct", + "title": "List is mutable — can change element in place", + "code": "l1 = [1, 2, 3]\nprint(l1) # [1, 2, 3]\nl1[2] = 4\nprint(l1) # [1, 2, 4]", + "why": "Immutable types like `int`, `float`, `str`, and `tuple` cannot change in place. Mutable types like `list`, `dict`, and `set` can be changed through the same object.", + "output": "", + "status": "curated", "subtopic_id": "w1-objects-and-names-core", - "subtopic_title": "Objects, Types, Mutability, Assignment, and Names", - "title": "Objects: core properties", - "explanation": "Every object has exactly one unique id (cannot change), exactly one type (cannot change), and exactly one value. The type defines what value can be stored and whether the value is mutable or immutable. An object can have zero, one, or more names bound to it. A name can only refer to one object at any time.", - "code_examples": [] + "subtopic_title": "Objects, Types, Mutability, Assignment, and Names" }, { - "id": "ks-eae9bf47dd", - "week": 1, - "source": "materials/lectures/Lecture Week 1.md", - "source_type": "lecture", - "topic": "Objects and Names", + "id": "ai-example-2", + "kind": "correct", + "title": "Tuple is immutable — assigning to index raises TypeError", + "code": "t1 = (1, 2, 3)\nt1[2] = 4\n# TypeError: 'tuple' object does not support item assignment", + "why": "Immutable types like `int`, `float`, `str`, and `tuple` cannot change in place. Mutable types like `list`, `dict`, and `set` can be changed through the same object.", + "output": "", + "status": "curated", "subtopic_id": "w1-objects-and-names-core", - "subtopic_title": "Objects, Types, Mutability, Assignment, and Names", - "title": "Mutable vs immutable types", - "explanation": "Immutable: int, float, str, bool, tuple. Mutable: list, dict, set. The value of a mutable object CAN be changed in-place. The value of an immutable object CANNOT be changed — a new object must be created.", - "code_examples": [ - { - "description": "List is mutable — can change element in place", - "code": "l1 = [1, 2, 3]\nprint(l1) # [1, 2, 3]\nl1[2] = 4\nprint(l1) # [1, 2, 4]" - }, - { - "description": "Tuple is immutable — assigning to index raises TypeError", - "code": "t1 = (1, 2, 3)\nt1[2] = 4\n# TypeError: 'tuple' object does not support item assignment" - }, - { - "description": "String reassignment creates a NEW object, not mutation", - "code": "box_1 = 'content'\nold_id = id(box_1)\nbox_1 = 'new content'\nnew_id = id(box_1)\nprint(old_id == new_id) # False — different object" - } - ] + "subtopic_title": "Objects, Types, Mutability, Assignment, and Names" }, { - "id": "ks-61c5deec4a", - "week": 1, - "source": "materials/lectures/Lecture Week 1.md", - "source_type": "lecture", - "topic": "Objects and Names", + "id": "ai-example-3", + "kind": "correct", + "title": "Basic assignment", + "code": "name_1 = 300\nprint(name_1) # 300\nprint(type(name_1)) # \nprint(id(name_1)) # some unique integer", + "why": "Assignment binds the left-hand name to the object produced on the right-hand side.", + "output": "", + "status": "curated", "subtopic_id": "w1-objects-and-names-core", - "subtopic_title": "Objects, Types, Mutability, Assignment, and Names", - "title": "Assignment statements — reading right to left", - "explanation": "Python creates a new object with the value on the right, infers type from the value, then binds the name on the left to that object.", - "code_examples": [ - { - "description": "Basic assignment", - "code": "name_1 = 300\nprint(name_1) # 300\nprint(type(name_1)) # \nprint(id(name_1)) # some unique integer" - }, - { - "description": "Two names bound to the same object (same id)", - "code": "name_3 = name_4 = name_5 = name_6 = 300\nprint(name_3 is name_4 is name_5 is name_6) # True" - }, - { - "description": "Two separate objects with equal value (different id)", - "code": "name_1 = 300\nname_2 = 300\nprint(name_1 == name_2) # True (same value)\nprint(id(name_1) != id(name_2)) # True (different objects)" - } - ] + "subtopic_title": "Objects, Types, Mutability, Assignment, and Names" }, { - "id": "ks-cb3a9e3fd2", - "week": 1, - "source": "materials/lectures/Lecture Week 1.md", - "source_type": "lecture", - "topic": "Objects and Names", + "id": "ai-example-4", + "kind": "correct", + "title": "Two names bound to the same object (same id)", + "code": "name_3 = name_4 = name_5 = name_6 = 300\nprint(name_3 is name_4 is name_5 is name_6) # True", + "why": "Assignment binds the left-hand name to the object produced on the right-hand side.", + "output": "", + "status": "curated", "subtopic_id": "w1-objects-and-names-core", - "subtopic_title": "Objects, Types, Mutability, Assignment, and Names", - "title": "Object types — the 8 types to know", - "explanation": "int, float, str, bool, tuple, list, dict, set", - "code_examples": [ - { - "description": "All 8 types", - "code": "var_1 = 123 # int\nvar_2 = 123.3 # float\nvar_3 = '123' # str\nvar_4 = True # bool\nvar_5 = ('123', 123) # tuple\nvar_6 = [123, '123'] # list\nvar_7 = {'k1': 'v1'} # dict\nvar_8 = {123, '123'} # set" - } - ] + "subtopic_title": "Objects, Types, Mutability, Assignment, and Names" }, { - "id": "ks-d79a1899f6", - "week": 1, - "source": "materials/lectures/Lecture Week 1.md", - "source_type": "lecture", - "topic": "Objects and Names", + "id": "ai-example-5", + "kind": "correct", + "title": "All 8 types", + "code": "var_1 = 123 # int\nvar_2 = 123.3 # float\nvar_3 = '123' # str\nvar_4 = True # bool\nvar_5 = ('123', 123) # tuple\nvar_6 = [123, '123'] # list\nvar_7 = {'k1': 'v1'} # dict\nvar_8 = {123, '123'} # set", + "why": "Core built-in types: `int`, `float`, `str`, `bool`, `tuple`, `list`, `dict`, `set`.", + "output": "", + "status": "curated", "subtopic_id": "w1-objects-and-names-core", - "subtopic_title": "Objects, Types, Mutability, Assignment, and Names", - "title": "Names / variable naming rules", - "explanation": "Names can consist of letters (upper/lower), digits, and underscores. Names CANNOT start with a digit. Names ARE case-sensitive (name_1 != Name_1). Avoid Python reserved words (e.g., don't name a variable 'sorted', 'list', 'print').", - "code_examples": [] + "subtopic_title": "Objects, Types, Mutability, Assignment, and Names" }, { - "id": "ks-6f41148083", - "week": 1, - "source": "materials/lectures/Lecture Week 1.md", - "source_type": "lecture", - "topic": "Objects and Names", + "id": "ai-example-6", + "kind": "correct", + "title": "Basic slicing examples", + "code": "l1 = [1, 2, 3, 4, 5, 6, 7, 8]\nprint(l1[7]) # 8\nprint(l1[-1]) # 8\nprint(l1[-5:5]) # [4, 5]\nprint(l1[:-5]) # [1, 2, 3]", + "why": "Syntax: seq[start:end:step]. Start is inclusive, end is NOT inclusive. Defaults: start=0, end=len, step=1. Negative step goes from right to left. Slicing always creates a NEW object of the same type.", + "output": "", + "status": "curated", "subtopic_id": "w1-objects-and-names-core", - "subtopic_title": "Objects, Types, Mutability, Assignment, and Names", - "title": "Slicing", - "explanation": "Syntax: seq[start:end:step]. Start is inclusive, end is NOT inclusive. Defaults: start=0, end=len, step=1. Negative step goes from right to left. Slicing always creates a NEW object of the same type.", - "code_examples": [ - { - "description": "Basic slicing examples", - "code": "l1 = [1, 2, 3, 4, 5, 6, 7, 8]\nprint(l1[7]) # 8\nprint(l1[-1]) # 8\nprint(l1[-5:5]) # [4, 5]\nprint(l1[:-5]) # [1, 2, 3]" - }, - { - "description": "Negative step", - "code": "l1 = [1, 2, 3, 4, 5, 6, 7, 8]\nprint(l1[5:1:-2]) # [6, 4]\nprint(l1[5::-1]) # [6, 5, 4, 3, 2, 1]\nprint(l1[:1:-1]) # [8, 7, 6, 5, 4, 3]\nprint(l1[1:5:-2]) # [] (already past end)" - }, - { - "description": "Slice reversal", - "code": "l1 = [1, 2, 3, 4]\nprint(l1[::-1]) # [4, 3, 2, 1]" - }, - { - "description": "Slicing creates new object — key exam trap", - "code": "l1 = [1, 2, 3, 4]\nl2 = l1\nl3 = l1[:]\nl1[-1] = 5\nprint(l1 == l2, l2 == l3) # True False (l3 is independent copy)" - }, - { - "description": "Changing a list slice vs index", - "code": "l1 = [1, 2, 3, 4, 5, 6]\nl1[1:2] = [1, 1] # replaces element at index 1 with two elements\nprint(l1) # [1, 1, 1, 3, 4, 5, 6]\n\nl1 = [1, 2, 3, 4, 5, 6]\nl1[1] = [1, 1] # replaces element at index 1 with a list\nprint(l1) # [1, [1, 1], 3, 4, 5, 6]" - }, - { - "description": "Slicing strings and tuples", - "code": "t1 = (1, 2, 3)\nprint(t1[1:]) # (2, 3)\ns1 = 'uva Amsterdam'\nprint(s1[5:-3:2]) # 'mtr'" - }, - { - "description": "Changing string/tuple (must create new object)", - "code": "s1 = 'uva Amsterdam'\n# s1[6] = 's' # ERROR\ns1 = s1[:6] + 's' + s1[7:]\nprint(s1) # works\n\nt1 = (1, 4, 3)\n# t1[1] = 2 # ERROR\nt1 = t1[:1] + (2,) + t1[2:]\nprint(t1) # works" - } - ] + "subtopic_title": "Objects, Types, Mutability, Assignment, and Names" }, { - "id": "ks-0153de2f70", - "week": 1, - "source": "materials/lectures/Lecture Week 1.md", - "source_type": "lecture", - "topic": "Objects and Names", + "id": "ai-example-7", + "kind": "correct", + "title": "Negative step", + "code": "l1 = [1, 2, 3, 4, 5, 6, 7, 8]\nprint(l1[5:1:-2]) # [6, 4]\nprint(l1[5::-1]) # [6, 5, 4, 3, 2, 1]\nprint(l1[:1:-1]) # [8, 7, 6, 5, 4, 3]\nprint(l1[1:5:-2]) # [] (already past end)", + "why": "Syntax: seq[start:end:step]. Start is inclusive, end is NOT inclusive. Defaults: start=0, end=len, step=1. Negative step goes from right to left. Slicing always creates a NEW object of the same type.", + "output": "", + "status": "curated", "subtopic_id": "w1-objects-and-names-core", - "subtopic_title": "Objects, Types, Mutability, Assignment, and Names", - "title": "Functions — basics", - "explanation": "Functions are objects. Defined with def. Called with (). Built-in functions: print, id, len, type, del. Functions can return values. Methods are functions attached to objects.", - "code_examples": [ - { - "description": "Simple function", - "code": "def size(length, width):\n return length * width\nprint(size(2,3)) # 6" - } - ] + "subtopic_title": "Objects, Types, Mutability, Assignment, and Names" }, { - "id": "ks-df3b849d59", - "week": 1, - "source": "materials/lectures/Lecture Week 1.md", - "source_type": "lecture", - "topic": "Objects and Names", + "id": "manual-objects-aliasing", + "kind": "correct", + "title": "Aliasing vs slicing copy", + "code": "l1 = [1, 2, 3]\nl2 = l1\nl3 = l1[:]\nl1[0] = 99\nprint(l2) # [99, 2, 3]\nprint(l3) # [1, 2, 3]", + "why": "For mutable objects, `l2 = l1` aliases the same object; use slicing like `l1[:]` when you need an independent copy.", + "output": "", + "status": "curated", "subtopic_id": "w1-objects-and-names-core", - "subtopic_title": "Objects, Types, Mutability, Assignment, and Names", - "title": "Exam question types", - "explanation": "Which code fragment will print the following output? / What will be printed by the following code fragment? / Which code fragment prints the SAME output as...? / One fragment prints different output from the others. / Which correctly solves the problem? Options may include: 'None of the above', 'Both', 'All', 'An error'.", - "code_examples": [] + "subtopic_title": "Objects, Types, Mutability, Assignment, and Names" }, { - "id": "ks-419e787b39", - "week": 1, - "source": "materials/notebooks/Notebook Week 1.ipynb", - "source_type": "notebook", - "topic": "Objects and Names", + "id": "ai-example-8", + "kind": "correct", + "title": "Simple function", + "code": "def size(length, width):\n return length * width\nprint(size(2,3)) # 6", + "why": "Functions are objects. Defined with def. Called with (). Built-in functions: print, id, len, type, del. Functions can return values. Methods are functions attached to objects.", + "output": "", + "status": "curated", "subtopic_id": "w1-objects-and-names-core", - "subtopic_title": "Objects, Types, Mutability, Assignment, and Names", - "title": "objects", - "explanation": "### Everything in Python is an object. Objects in Python have one id, one value, one type, and zero or more names\n
    An assignment statement is one of the ways to create an object. An object created with an assignment statement will have a name, an id, a value and a type.\n
    If you know the name you can ask for the id, the value, and the type", - "code_examples": [] + "subtopic_title": "Objects, Types, Mutability, Assignment, and Names" } ], + "ai_summary": { + "status": "curated", + "content": "Objects have identity, type, and value. Names bind to objects; rebinding changes the name, while mutation only matters for mutable objects.", + "generator": "lecture-first-build", + "model": null + }, "exam_questions": [ { "id": "exam-trial_midterm-1-w1-objects-and-names", @@ -1202,193 +1009,7 @@ "explanation": "Option A correctly iterates over the list of dictionaries and uses f-strings with proper quote escaping (single quotes inside double quotes) and the `:.1f` format specifier to display the float to one decimal place." } ], - "notebook_snippets": [ - { - "id": "cs-cd4f0b5c6e", - "week": 1, - "cell_index": null, - "cell_type": "code", - "source_type": "notebook", - "topic": "Objects and Names", - "subtopic_id": "w1-objects-and-names-core", - "subtopic_title": "Objects, Types, Mutability, Assignment, and Names", - "title": "type_conversion", - "source": "integer_list = [1, 2, 3, 1]\nletter_list = ['a', 'b', 'c', 'd']\nprint(set(integer_list))\nprint(tuple(integer_list))\nprint(dict(zip(letter_list, integer_list)))\n\ninteger_tuple = (1, 2, 3, 1)\nletter_tuple = ('a', 'b', 'c', 'd')\nprint(set(integer_tuple))\nprint(list(integer_tuple))\nprint(dict(zip(letter_tuple, integer_tuple)))\n\ninteger_set = {1, 2, 3}\nletter_set = {'a', 'b', 'c'}\nprint(list(integer_set))\nprint(tuple(letter_set))\nprint(dict(zip(integer_set, letter_set)))\n\nd_1 = {1: 'c', 2: 'b', 3: 'a'}\nprint(list(d_1))\nprint(tuple(d_1))\nprint(set(d_1))", - "outputs": [] - }, - { - "id": "cs-b65f3408e3", - "week": 1, - "cell_index": null, - "cell_type": "code", - "source_type": "notebook", - "topic": "Objects and Names", - "subtopic_id": "w1-objects-and-names-core", - "subtopic_title": "Objects, Types, Mutability, Assignment, and Names", - "title": "objects", - "source": "a = 1\nprint(id(a))\nprint(a)\nprint(type(a))", - "outputs": [] - }, - { - "id": "cs-d185f0c824", - "week": 1, - "cell_index": null, - "cell_type": "code", - "source_type": "notebook", - "topic": "Objects and Names", - "subtopic_id": "w1-objects-and-names-core", - "subtopic_title": "Objects, Types, Mutability, Assignment, and Names", - "title": "identity_id", - "source": "var_1 = 123\nprint(id(var_1))\nvar_1 = 321\nprint(id(var_1))", - "outputs": [] - }, - { - "id": "cs-04169579a8", - "week": 1, - "cell_index": null, - "cell_type": "code", - "source_type": "notebook", - "topic": "Objects and Names", - "subtopic_id": "w1-objects-and-names-core", - "subtopic_title": "Objects, Types, Mutability, Assignment, and Names", - "title": "assignment", - "source": "a = 100\nb = 200\nc = 300\nd, e, f = a, b, c\nprint(a, b, c)\nprint(d, e, f)", - "outputs": [] - }, - { - "id": "cs-58c37dfe80", - "week": 1, - "cell_index": null, - "cell_type": "code", - "source_type": "notebook", - "topic": "Objects and Names", - "subtopic_id": "w1-objects-and-names-core", - "subtopic_title": "Objects, Types, Mutability, Assignment, and Names", - "title": "assignment", - "source": "a = 100\nb = 200\nc = 300\nprint(a, b, c)\nb, c, a = a, b, c \nprint(a, b, c)", - "outputs": [] - }, - { - "id": "cs-ef4e6233fe", - "week": 1, - "cell_index": null, - "cell_type": "code", - "source_type": "notebook", - "topic": "Objects and Names", - "subtopic_id": "w1-objects-and-names-core", - "subtopic_title": "Objects, Types, Mutability, Assignment, and Names", - "title": "names", - "source": "var_1 = 100\nprint(id(var_1))\nvar_1 = 200\nprint(id(var_1))\ndel(var_1)\nprint(id(var_1))", - "outputs": [] - }, - { - "id": "cs-94491b4b00", - "week": 1, - "cell_index": null, - "cell_type": "code", - "source_type": "notebook", - "topic": "Objects and Names", - "subtopic_id": "w1-objects-and-names-core", - "subtopic_title": "Objects, Types, Mutability, Assignment, and Names", - "title": "mutable_immutable", - "source": "var_1 = (100, '100')\nid1 = id(var_1)\nvar_1[1] = '110'\nid2 = id(var_1)\nprint(id1 == id2)", - "outputs": [] - }, - { - "id": "cs-33e88a778b", - "week": 1, - "cell_index": null, - "cell_type": "code", - "source_type": "notebook", - "topic": "Objects and Names", - "subtopic_id": "w1-objects-and-names-core", - "subtopic_title": "Objects, Types, Mutability, Assignment, and Names", - "title": "identity_id", - "source": "var_1 = 321\nprint(id(var_1))\nvar_2 = 321\nprint(id(var_2))\nprint(var_1 == var_2)\nprint(var_1 is var_2)", - "outputs": [] - } - ], - "ai_summary": { - "status": "curated", - "content": "Objects have identity, type, and value. Names bind to objects; rebinding changes the name, while mutation only matters for mutable objects.", - "generator": "lecture-first-build", - "model": null - }, - "ai_common_questions": { - "status": "curated", - "bullets": [ - "Assume you already have a variable called x, which contains a list of integers.\nWhich of the following programs will print you a list of the squared values of the elements in x?", - "Suppose you have the following function:\ndef multiply(*args, factor=2):\ntotal = 1\nfor num in args:\ntotal *= num\nreturn total * factor\nWhich of the following functions will return the same values as the function above, if we call the function thrice as follows…", - "Assume you have the following variables:\nx = 3\ny = 3.0\nz = '3'\nWhat will be printed by the following code:\nprint((x != z and x == int(z)) or (x != y and y != z))\nA 3\nB The code will result in an error.\nC False\nD True", - "You need to write a function called dict_keys that checks whether a certain key is in available in a certain dictionary.", - "l2=l1 vs l2=l1[:] — l2=l1 shares the SAME object, slicing creates independent copy", - "def f(lst=[]): — the [] is created ONCE at def time and persists across calls. Fix: use None and create inside function" - ], - "items": [ - { - "id": "aiq-1", - "summary": "Which of the following statements is correct? I: Two objects can have different values, while having the same type. II: Two objects can have the same value, while having different types.", - "detail": "I is correct (e.g. a=1, b=2, both int). II is incorrect — if two objects have the same value they must have the same type.", - "extra": "Objects/types", - "subtopic_id": "w1-objects-and-names-core", - "subtopic_title": "Objects, Types, Mutability, Assignment, and Names" - }, - { - "id": "aiq-2", - "summary": "Why does the following code work even though strings are immutable?", - "detail": "Decide whether the code is rebinding a name or mutating a shared mutable object.", - "extra": "Immutability/names", - "subtopic_id": "w1-objects-and-names-core", - "subtopic_title": "Objects, Types, Mutability, Assignment, and Names" - }, - { - "id": "aiq-3", - "summary": "Assume you already have a variable called x, which contains a list of integers.", - "detail": "Expand `range(start, stop, step)` manually; `stop` is excluded and the next value is found by adding `step` each time.", - "extra": "Exam • trial_midterm • Q1", - "subtopic_id": "w1-objects-and-names-core", - "subtopic_title": "Objects, Types, Mutability, Assignment, and Names", - "code": "For example:\nIf x = [1, 2, 4, 8]\nthe program should prints:\n[1, 4, 16, 64].\nA mylist = []\nfor i in x:\nmylist[i] = x[i]**2\nprint(mylist)\nB mylist = [0] * len(x)\nfor i in range(len(x)):\nmylist[i] = x[i]**2\nprint(mylist)" - }, - { - "id": "aiq-4", - "summary": "Suppose you have the following function:", - "detail": "Trace the returned value, not just what gets printed while the function runs.", - "extra": "Exam • trial_midterm • Q3", - "subtopic_id": "w1-objects-and-names-core", - "subtopic_title": "Objects, Types, Mutability, Assignment, and Names", - "code": "Suppose you have the following function:\ndef multiply(*args, factor=2):\ntotal = 1\nfor num in args:\ntotal *= num\nreturn total * factor\nWhich of the following functions will return the same values as the function above, if we call the function thrice as follows:\nmultiply(1, 2, factor=3)\nmultiply(3, 4)\nmultiply()\nA def multiply(*args, factor=2):\ntotal = args[0]" - }, - { - "id": "aiq-5", - "summary": "Assume you have the following variables:", - "detail": "Decide whether the code is rebinding a name or mutating a shared mutable object.", - "extra": "Exam • trial_midterm • Q4", - "subtopic_id": "w1-objects-and-names-core", - "subtopic_title": "Objects, Types, Mutability, Assignment, and Names", - "code": "Assume you have the following variables:\nx = 3\ny = 3.0\nz = '3'\nWhat will be printed by the following code:\nprint((x != z and x == int(z)) or (x != y and y != z))\nA 3\nB The code will result in an error.\nC False\nD True" - }, - { - "id": "aiq-6", - "summary": "Slicing creates a NEW object", - "detail": "l2=l1 vs l2=l1[:] — l2=l1 shares the SAME object, slicing creates independent copy", - "extra": "", - "subtopic_id": "", - "subtopic_title": "" - }, - { - "id": "aiq-7", - "summary": "Mutable default argument", - "detail": "def f(lst=[]): — the [] is created ONCE at def time and persists across calls. Fix: use None and create inside function", - "extra": "", - "subtopic_id": "", - "subtopic_title": "" - } - ], - "generator": "lecture-first-build", - "model": null - }, - "key_points_to_remember": [ + "key_points_to_remember": [ { "id": "kp-1", "text": "Each object has identity, type, and value. Names bind to objects; rebinding changes the name, while in-place changes only affect mutable objects.", @@ -1550,631 +1171,435 @@ "details": [] } ], - "ai_examples": [ + "lecture_snippets": [ { - "id": "ai-example-1", - "kind": "correct", - "title": "List is mutable — can change element in place", - "code": "l1 = [1, 2, 3]\nprint(l1) # [1, 2, 3]\nl1[2] = 4\nprint(l1) # [1, 2, 4]", - "why": "Immutable types like `int`, `float`, `str`, and `tuple` cannot change in place. Mutable types like `list`, `dict`, and `set` can be changed through the same object.", - "output": "", - "status": "curated", + "id": "ks-e88d0a8060", + "week": 1, + "source": "materials/lectures/Lecture Week 1.md", + "source_type": "lecture", + "topic": "Objects and Names", "subtopic_id": "w1-objects-and-names-core", - "subtopic_title": "Objects, Types, Mutability, Assignment, and Names" + "subtopic_title": "Objects, Types, Mutability, Assignment, and Names", + "title": "Objects: core properties", + "explanation": "Every object has exactly one unique id (cannot change), exactly one type (cannot change), and exactly one value. The type defines what value can be stored and whether the value is mutable or immutable. An object can have zero, one, or more names bound to it. A name can only refer to one object at any time.", + "code_examples": [] }, { - "id": "ai-example-2", - "kind": "correct", - "title": "Tuple is immutable — assigning to index raises TypeError", - "code": "t1 = (1, 2, 3)\nt1[2] = 4\n# TypeError: 'tuple' object does not support item assignment", - "why": "Immutable types like `int`, `float`, `str`, and `tuple` cannot change in place. Mutable types like `list`, `dict`, and `set` can be changed through the same object.", - "output": "", - "status": "curated", + "id": "ks-eae9bf47dd", + "week": 1, + "source": "materials/lectures/Lecture Week 1.md", + "source_type": "lecture", + "topic": "Objects and Names", "subtopic_id": "w1-objects-and-names-core", - "subtopic_title": "Objects, Types, Mutability, Assignment, and Names" + "subtopic_title": "Objects, Types, Mutability, Assignment, and Names", + "title": "Mutable vs immutable types", + "explanation": "Immutable: int, float, str, bool, tuple. Mutable: list, dict, set. The value of a mutable object CAN be changed in-place. The value of an immutable object CANNOT be changed — a new object must be created.", + "code_examples": [ + { + "description": "List is mutable — can change element in place", + "code": "l1 = [1, 2, 3]\nprint(l1) # [1, 2, 3]\nl1[2] = 4\nprint(l1) # [1, 2, 4]" + }, + { + "description": "Tuple is immutable — assigning to index raises TypeError", + "code": "t1 = (1, 2, 3)\nt1[2] = 4\n# TypeError: 'tuple' object does not support item assignment" + }, + { + "description": "String reassignment creates a NEW object, not mutation", + "code": "box_1 = 'content'\nold_id = id(box_1)\nbox_1 = 'new content'\nnew_id = id(box_1)\nprint(old_id == new_id) # False — different object" + } + ] }, { - "id": "ai-example-3", - "kind": "correct", - "title": "Basic assignment", - "code": "name_1 = 300\nprint(name_1) # 300\nprint(type(name_1)) # \nprint(id(name_1)) # some unique integer", - "why": "Assignment binds the left-hand name to the object produced on the right-hand side.", - "output": "", - "status": "curated", + "id": "ks-61c5deec4a", + "week": 1, + "source": "materials/lectures/Lecture Week 1.md", + "source_type": "lecture", + "topic": "Objects and Names", "subtopic_id": "w1-objects-and-names-core", - "subtopic_title": "Objects, Types, Mutability, Assignment, and Names" + "subtopic_title": "Objects, Types, Mutability, Assignment, and Names", + "title": "Assignment statements — reading right to left", + "explanation": "Python creates a new object with the value on the right, infers type from the value, then binds the name on the left to that object.", + "code_examples": [ + { + "description": "Basic assignment", + "code": "name_1 = 300\nprint(name_1) # 300\nprint(type(name_1)) # \nprint(id(name_1)) # some unique integer" + }, + { + "description": "Two names bound to the same object (same id)", + "code": "name_3 = name_4 = name_5 = name_6 = 300\nprint(name_3 is name_4 is name_5 is name_6) # True" + }, + { + "description": "Two separate objects with equal value (different id)", + "code": "name_1 = 300\nname_2 = 300\nprint(name_1 == name_2) # True (same value)\nprint(id(name_1) != id(name_2)) # True (different objects)" + } + ] }, { - "id": "ai-example-4", - "kind": "correct", - "title": "Two names bound to the same object (same id)", - "code": "name_3 = name_4 = name_5 = name_6 = 300\nprint(name_3 is name_4 is name_5 is name_6) # True", - "why": "Assignment binds the left-hand name to the object produced on the right-hand side.", - "output": "", - "status": "curated", - "subtopic_id": "w1-objects-and-names-core", - "subtopic_title": "Objects, Types, Mutability, Assignment, and Names" - }, - { - "id": "ai-example-5", - "kind": "correct", - "title": "All 8 types", - "code": "var_1 = 123 # int\nvar_2 = 123.3 # float\nvar_3 = '123' # str\nvar_4 = True # bool\nvar_5 = ('123', 123) # tuple\nvar_6 = [123, '123'] # list\nvar_7 = {'k1': 'v1'} # dict\nvar_8 = {123, '123'} # set", - "why": "Core built-in types: `int`, `float`, `str`, `bool`, `tuple`, `list`, `dict`, `set`.", - "output": "", - "status": "curated", - "subtopic_id": "w1-objects-and-names-core", - "subtopic_title": "Objects, Types, Mutability, Assignment, and Names" - }, - { - "id": "ai-example-6", - "kind": "correct", - "title": "Basic slicing examples", - "code": "l1 = [1, 2, 3, 4, 5, 6, 7, 8]\nprint(l1[7]) # 8\nprint(l1[-1]) # 8\nprint(l1[-5:5]) # [4, 5]\nprint(l1[:-5]) # [1, 2, 3]", - "why": "Syntax: seq[start:end:step]. Start is inclusive, end is NOT inclusive. Defaults: start=0, end=len, step=1. Negative step goes from right to left. Slicing always creates a NEW object of the same type.", - "output": "", - "status": "curated", - "subtopic_id": "w1-objects-and-names-core", - "subtopic_title": "Objects, Types, Mutability, Assignment, and Names" - }, - { - "id": "ai-example-7", - "kind": "correct", - "title": "Negative step", - "code": "l1 = [1, 2, 3, 4, 5, 6, 7, 8]\nprint(l1[5:1:-2]) # [6, 4]\nprint(l1[5::-1]) # [6, 5, 4, 3, 2, 1]\nprint(l1[:1:-1]) # [8, 7, 6, 5, 4, 3]\nprint(l1[1:5:-2]) # [] (already past end)", - "why": "Syntax: seq[start:end:step]. Start is inclusive, end is NOT inclusive. Defaults: start=0, end=len, step=1. Negative step goes from right to left. Slicing always creates a NEW object of the same type.", - "output": "", - "status": "curated", - "subtopic_id": "w1-objects-and-names-core", - "subtopic_title": "Objects, Types, Mutability, Assignment, and Names" - }, - { - "id": "manual-objects-aliasing", - "kind": "correct", - "title": "Aliasing vs slicing copy", - "code": "l1 = [1, 2, 3]\nl2 = l1\nl3 = l1[:]\nl1[0] = 99\nprint(l2) # [99, 2, 3]\nprint(l3) # [1, 2, 3]", - "why": "For mutable objects, `l2 = l1` aliases the same object; use slicing like `l1[:]` when you need an independent copy.", - "output": "", - "status": "curated", - "subtopic_id": "w1-objects-and-names-core", - "subtopic_title": "Objects, Types, Mutability, Assignment, and Names" - }, - { - "id": "ai-example-8", - "kind": "correct", - "title": "Simple function", - "code": "def size(length, width):\n return length * width\nprint(size(2,3)) # 6", - "why": "Functions are objects. Defined with def. Called with (). Built-in functions: print, id, len, type, del. Functions can return values. Methods are functions attached to objects.", - "output": "", - "status": "curated", - "subtopic_id": "w1-objects-and-names-core", - "subtopic_title": "Objects, Types, Mutability, Assignment, and Names" - } - ], - "recommended_ids": [ - "exam-trial_midterm-1-w1-objects-and-names", - "exam-trial_midterm-3-w1-objects-and-names", - "exam-trial_midterm-4-w1-objects-and-names", - "exam-trial_midterm-7-w1-objects-and-names", - "ks-e88d0a8060", - "ks-eae9bf47dd", - "ks-61c5deec4a", - "ks-cb3a9e3fd2" - ] - } - }, - { - "id": "w1-operators-and-truth", - "topic": "Operators and Truth", - "canonical_topic": "w1-operators-and-truth", - "weeks": [ - 1 - ], - "week_id": "week-1", - "topic_meta": { - "week": 1, - "week_id": "week-1", - "week_title": "Week 1", - "topic_id": "w1-operators-and-truth", - "topic_title": "Operators and Truth", - "topic_order": 3 - }, - "subtopics": [ - { - "id": "w1-operators-and-truth-core", - "title": "Arithmetic, Comparison, and Boolean Operators", - "order": 1, - "summary": "Know arithmetic, comparison, and boolean precedence. Distinguish `/` vs `//`, `**` vs `^`, and trace truth values with `not`, `and`, and `or`.", - "item_ids": { - "lecture_snippet_ids": [ - "ks-03c874b8bb", - "ks-c0135e2a4a", - "ks-c815ffe1d5" - ], - "exam_question_ids": [], - "notebook_snippet_ids": [ - "cs-7eb8617d28", - "cs-3cb4b8e8f9", - "cs-266616a010", - "cs-4f8a5f420b", - "cs-5edb9a0b07", - "cs-eb7fa31fd3", - "cs-4b73ab2680" - ], - "example_ids": [ - "ai-example-1", - "ai-example-2", - "ai-example-3", - "ai-example-4", - "ai-example-5", - "ai-example-6", - "ai-example-7", - "ai-example-8" - ], - "key_point_ids": [ - "kp-1", - "kp-2" - ] - } - } - ], - "exam_stats": { - "total_hits": 0, - "by_exam": {}, - "coverage_count": 0 - }, - "related_topics": [ - "Arithmetic, Comparison, and Boolean Operators" - ], - "trap_patterns": [ - { - "pattern": "Boolean operator precedence: not > and > or", - "trap": "a==1 or a==2 and b==1 or b==2 is evaluated as a==1 or (a==2 and b==1) or b==2", - "weeks": [ - 1, - 2 - ], - "appears_in_exams": [ - "midterm_2023", - "extra_practice" - ] - } - ], - "sections": { - "lecture_snippets": [ - { - "id": "ks-03c874b8bb", + "id": "ks-cb3a9e3fd2", "week": 1, "source": "materials/lectures/Lecture Week 1.md", "source_type": "lecture", - "topic": "Operators and Truth", - "subtopic_id": "w1-operators-and-truth-core", - "subtopic_title": "Arithmetic, Comparison, and Boolean Operators", - "title": "Arithmetic operators", - "explanation": "a+b, a-b, a*b: standard. a/b: always returns float. a//b: floor division (highest integer <= result). a%b: remainder. a**b: exponentiation. NOTE: ^ is NOT exponentiation in Python (it is XOR). (a//b)*b + a%b == a always.", + "topic": "Objects and Names", + "subtopic_id": "w1-objects-and-names-core", + "subtopic_title": "Objects, Types, Mutability, Assignment, and Names", + "title": "Object types — the 8 types to know", + "explanation": "int, float, str, bool, tuple, list, dict, set", "code_examples": [ { - "description": "Floor division and modulo", - "code": "print(5 // 3, 5 % 3) # 1 2\nprint(-5 // 3, -5 % 3) # -2 1\nprint(5 // 2, 5 % 2) # 2 1\nprint(-5 // 2, -5 % 2) # -3 1" + "description": "All 8 types", + "code": "var_1 = 123 # int\nvar_2 = 123.3 # float\nvar_3 = '123' # str\nvar_4 = True # bool\nvar_5 = ('123', 123) # tuple\nvar_6 = [123, '123'] # list\nvar_7 = {'k1': 'v1'} # dict\nvar_8 = {123, '123'} # set" } ] }, { - "id": "ks-c0135e2a4a", + "id": "ks-d79a1899f6", "week": 1, "source": "materials/lectures/Lecture Week 1.md", "source_type": "lecture", - "topic": "Operators and Truth", - "subtopic_id": "w1-operators-and-truth-core", - "subtopic_title": "Arithmetic, Comparison, and Boolean Operators", - "title": "Comparison operators", - "explanation": "==, !=, >, <, >=, <=. Always return True or False. Comparing floats can be tricky: 1.1+2.2 != 3.3 in Python due to floating-point precision. String/tuple/list comparison is element-by-element left to right; first differing element decides; if equal length and no differences, they are equal; shorter sequence is 'less than' longer if all elements match up to shorter length.", + "topic": "Objects and Names", + "subtopic_id": "w1-objects-and-names-core", + "subtopic_title": "Objects, Types, Mutability, Assignment, and Names", + "title": "Names / variable naming rules", + "explanation": "Names can consist of letters (upper/lower), digits, and underscores. Names CANNOT start with a digit. Names ARE case-sensitive (name_1 != Name_1). Avoid Python reserved words (e.g., don't name a variable 'sorted', 'list', 'print').", + "code_examples": [] + }, + { + "id": "ks-6f41148083", + "week": 1, + "source": "materials/lectures/Lecture Week 1.md", + "source_type": "lecture", + "topic": "Objects and Names", + "subtopic_id": "w1-objects-and-names-core", + "subtopic_title": "Objects, Types, Mutability, Assignment, and Names", + "title": "Slicing", + "explanation": "Syntax: seq[start:end:step]. Start is inclusive, end is NOT inclusive. Defaults: start=0, end=len, step=1. Negative step goes from right to left. Slicing always creates a NEW object of the same type.", "code_examples": [ { - "description": "Float precision issue", - "code": "print(1.1 + 2.2 == 3.3) # False" + "description": "Basic slicing examples", + "code": "l1 = [1, 2, 3, 4, 5, 6, 7, 8]\nprint(l1[7]) # 8\nprint(l1[-1]) # 8\nprint(l1[-5:5]) # [4, 5]\nprint(l1[:-5]) # [1, 2, 3]" }, { - "description": "List/tuple comparison", - "code": "print([1, 2, 3] < [1, 2, 3, 0]) # True (shorter is less)\nprint([2] < [1, 2, 3, 0]) # False (2 > 1 at index 0)" + "description": "Negative step", + "code": "l1 = [1, 2, 3, 4, 5, 6, 7, 8]\nprint(l1[5:1:-2]) # [6, 4]\nprint(l1[5::-1]) # [6, 5, 4, 3, 2, 1]\nprint(l1[:1:-1]) # [8, 7, 6, 5, 4, 3]\nprint(l1[1:5:-2]) # [] (already past end)" + }, + { + "description": "Slice reversal", + "code": "l1 = [1, 2, 3, 4]\nprint(l1[::-1]) # [4, 3, 2, 1]" + }, + { + "description": "Slicing creates new object — key exam trap", + "code": "l1 = [1, 2, 3, 4]\nl2 = l1\nl3 = l1[:]\nl1[-1] = 5\nprint(l1 == l2, l2 == l3) # True False (l3 is independent copy)" + }, + { + "description": "Changing a list slice vs index", + "code": "l1 = [1, 2, 3, 4, 5, 6]\nl1[1:2] = [1, 1] # replaces element at index 1 with two elements\nprint(l1) # [1, 1, 1, 3, 4, 5, 6]\n\nl1 = [1, 2, 3, 4, 5, 6]\nl1[1] = [1, 1] # replaces element at index 1 with a list\nprint(l1) # [1, [1, 1], 3, 4, 5, 6]" + }, + { + "description": "Slicing strings and tuples", + "code": "t1 = (1, 2, 3)\nprint(t1[1:]) # (2, 3)\ns1 = 'uva Amsterdam'\nprint(s1[5:-3:2]) # 'mtr'" + }, + { + "description": "Changing string/tuple (must create new object)", + "code": "s1 = 'uva Amsterdam'\n# s1[6] = 's' # ERROR\ns1 = s1[:6] + 's' + s1[7:]\nprint(s1) # works\n\nt1 = (1, 4, 3)\n# t1[1] = 2 # ERROR\nt1 = t1[:1] + (2,) + t1[2:]\nprint(t1) # works" } ] }, { - "id": "ks-c815ffe1d5", + "id": "ks-0153de2f70", "week": 1, "source": "materials/lectures/Lecture Week 1.md", "source_type": "lecture", - "topic": "Operators and Truth", - "subtopic_id": "w1-operators-and-truth-core", - "subtopic_title": "Arithmetic, Comparison, and Boolean Operators", - "title": "Boolean operators", - "explanation": "x and y: True only if both True. x or y: False only if both False. not x: inverts. NOTE: && and || are Python operators but do something different (bitwise). Precedence: 'not' first, then 'and', then 'or'. Use parentheses to avoid confusion.", + "topic": "Objects and Names", + "subtopic_id": "w1-objects-and-names-core", + "subtopic_title": "Objects, Types, Mutability, Assignment, and Names", + "title": "Functions — basics", + "explanation": "Functions are objects. Defined with def. Called with (). Built-in functions: print, id, len, type, del. Functions can return values. Methods are functions attached to objects.", "code_examples": [ { - "description": "Precedence trap", - "code": "a=1; b=3\nprint(a==1 or a==2 and b==1 or b==2) # True (WRONG: and binds tighter)\nprint((a==1 or a==2) and (b==1 or b==2)) # False (CORRECT)" + "description": "Simple function", + "code": "def size(length, width):\n return length * width\nprint(size(2,3)) # 6" } ] - } - ], - "exam_questions": [], - "notebook_snippets": [ + }, { - "id": "cs-7eb8617d28", + "id": "ks-df3b849d59", "week": 1, - "cell_index": null, - "cell_type": "code", - "source_type": "notebook", - "topic": "Operators and Truth", - "subtopic_id": "w1-operators-and-truth-core", - "subtopic_title": "Arithmetic, Comparison, and Boolean Operators", - "title": "arithmetic_operators", - "source": "print(5//2, 5%2)", - "outputs": [ - "2 1" - ] + "source": "materials/lectures/Lecture Week 1.md", + "source_type": "lecture", + "topic": "Objects and Names", + "subtopic_id": "w1-objects-and-names-core", + "subtopic_title": "Objects, Types, Mutability, Assignment, and Names", + "title": "Exam question types", + "explanation": "Which code fragment will print the following output? / What will be printed by the following code fragment? / Which code fragment prints the SAME output as...? / One fragment prints different output from the others. / Which correctly solves the problem? Options may include: 'None of the above', 'Both', 'All', 'An error'.", + "code_examples": [] }, { - "id": "cs-3cb4b8e8f9", + "id": "ks-419e787b39", + "week": 1, + "source": "materials/notebooks/Notebook Week 1.ipynb", + "source_type": "notebook", + "topic": "Objects and Names", + "subtopic_id": "w1-objects-and-names-core", + "subtopic_title": "Objects, Types, Mutability, Assignment, and Names", + "title": "objects", + "explanation": "### Everything in Python is an object. Objects in Python have one id, one value, one type, and zero or more names\n
    An assignment statement is one of the ways to create an object. An object created with an assignment statement will have a name, an id, a value and a type.\n
    If you know the name you can ask for the id, the value, and the type", + "code_examples": [] + } + ], + "notebook_snippets": [ + { + "id": "cs-cd4f0b5c6e", "week": 1, "cell_index": null, "cell_type": "code", "source_type": "notebook", - "topic": "Operators and Truth", - "subtopic_id": "w1-operators-and-truth-core", - "subtopic_title": "Arithmetic, Comparison, and Boolean Operators", - "title": "arithmetic_operators", - "source": "print(4 + 3)\nprint(4 - 3)\nprint(4 * 3)\nprint(4 / 3)\nprint(4 / 2)\nprint(4 ** 3)", - "outputs": [ - "7\n1\n12\n1.3333333333333333\n2.0\n64" - ] + "topic": "Objects and Names", + "subtopic_id": "w1-objects-and-names-core", + "subtopic_title": "Objects, Types, Mutability, Assignment, and Names", + "title": "type_conversion", + "source": "integer_list = [1, 2, 3, 1]\nletter_list = ['a', 'b', 'c', 'd']\nprint(set(integer_list))\nprint(tuple(integer_list))\nprint(dict(zip(letter_list, integer_list)))\n\ninteger_tuple = (1, 2, 3, 1)\nletter_tuple = ('a', 'b', 'c', 'd')\nprint(set(integer_tuple))\nprint(list(integer_tuple))\nprint(dict(zip(letter_tuple, integer_tuple)))\n\ninteger_set = {1, 2, 3}\nletter_set = {'a', 'b', 'c'}\nprint(list(integer_set))\nprint(tuple(letter_set))\nprint(dict(zip(integer_set, letter_set)))\n\nd_1 = {1: 'c', 2: 'b', 3: 'a'}\nprint(list(d_1))\nprint(tuple(d_1))\nprint(set(d_1))", + "outputs": [] }, { - "id": "cs-266616a010", + "id": "cs-b65f3408e3", "week": 1, "cell_index": null, "cell_type": "code", "source_type": "notebook", - "topic": "Operators and Truth", - "subtopic_id": "w1-operators-and-truth-core", - "subtopic_title": "Arithmetic, Comparison, and Boolean Operators", - "title": "arithmetic_operators", - "source": "print(5 // 3, 5 % 3)\nprint(-5 // 3, -5 % 3)\nprint(5 // 2, 5 % 2)\nprint(-5 // 2, -5 % 2)", - "outputs": [ - "1 2\n-2 1\n2 1\n-3 1" - ] + "topic": "Objects and Names", + "subtopic_id": "w1-objects-and-names-core", + "subtopic_title": "Objects, Types, Mutability, Assignment, and Names", + "title": "objects", + "source": "a = 1\nprint(id(a))\nprint(a)\nprint(type(a))", + "outputs": [] }, { - "id": "cs-4f8a5f420b", + "id": "cs-d185f0c824", "week": 1, "cell_index": null, "cell_type": "code", "source_type": "notebook", - "topic": "Operators and Truth", - "subtopic_id": "w1-operators-and-truth-core", - "subtopic_title": "Arithmetic, Comparison, and Boolean Operators", - "title": "arithmetic_operators", - "source": "#\nimport random # The random module that can be used to generate pseudo-random numbers is part of the standard Python installation\n # but the name has still to be importent\na = random.randint(3, 9) # This generates an integer between 3 and 9 (both included), it is given the name 'a'\nb = random.randint(3, 9) # # This generates an integer between 3 and 9 (both included), it is given the name 'b'\nprint (a, b)\nprint(a==(a/b)*b + a%b) # == compares what is left of it to what is right of it and evaluates to True if both sides evaluate to the same value", - "outputs": [ - "8 4\nTrue" - ] + "topic": "Objects and Names", + "subtopic_id": "w1-objects-and-names-core", + "subtopic_title": "Objects, Types, Mutability, Assignment, and Names", + "title": "identity_id", + "source": "var_1 = 123\nprint(id(var_1))\nvar_1 = 321\nprint(id(var_1))", + "outputs": [] }, { - "id": "cs-5edb9a0b07", + "id": "cs-04169579a8", "week": 1, "cell_index": null, "cell_type": "code", "source_type": "notebook", - "topic": "Operators and Truth", - "subtopic_id": "w1-operators-and-truth-core", - "subtopic_title": "Arithmetic, Comparison, and Boolean Operators", - "title": "comparison_operators", - "source": "print(1.1, 2.2, 1.1 + 2.2 == 3.3)", + "topic": "Objects and Names", + "subtopic_id": "w1-objects-and-names-core", + "subtopic_title": "Objects, Types, Mutability, Assignment, and Names", + "title": "assignment", + "source": "a = 100\nb = 200\nc = 300\nd, e, f = a, b, c\nprint(a, b, c)\nprint(d, e, f)", "outputs": [] }, { - "id": "cs-eb7fa31fd3", + "id": "cs-58c37dfe80", "week": 1, "cell_index": null, "cell_type": "code", "source_type": "notebook", - "topic": "Operators and Truth", - "subtopic_id": "w1-operators-and-truth-core", - "subtopic_title": "Arithmetic, Comparison, and Boolean Operators", - "title": "comparison_operators", - "source": "print(3 == 2)\nprint(3 > 3)\nprint(3 < 4)\nprint(3 >= 2)\nprint(3 <= 3)\nprint(3 != 4)", + "topic": "Objects and Names", + "subtopic_id": "w1-objects-and-names-core", + "subtopic_title": "Objects, Types, Mutability, Assignment, and Names", + "title": "assignment", + "source": "a = 100\nb = 200\nc = 300\nprint(a, b, c)\nb, c, a = a, b, c \nprint(a, b, c)", "outputs": [] }, { - "id": "cs-4b73ab2680", + "id": "cs-ef4e6233fe", "week": 1, "cell_index": null, "cell_type": "code", "source_type": "notebook", - "topic": "Operators and Truth", - "subtopic_id": "w1-operators-and-truth-core", - "subtopic_title": "Arithmetic, Comparison, and Boolean Operators", - "title": "comparison_operators", - "source": "print([1, 2, 3] < [1, 2, 3, 0])\nprint([2] < [1, 2, 3, 0])\nprint((1, 2, 3, 0) < (1, 2, 3))\nprint((2,) >= (1, 2, 3, 0))\nprint('abc' < 'abc ')\nprint('b' < 'abc ')\nprint('123' < '123 ')\nprint('2' < '123 ')", + "topic": "Objects and Names", + "subtopic_id": "w1-objects-and-names-core", + "subtopic_title": "Objects, Types, Mutability, Assignment, and Names", + "title": "names", + "source": "var_1 = 100\nprint(id(var_1))\nvar_1 = 200\nprint(id(var_1))\ndel(var_1)\nprint(id(var_1))", "outputs": [] - } - ], - "ai_summary": { - "status": "curated", - "content": "Know arithmetic, comparison, and boolean precedence. Distinguish `/` vs `//`, `**` vs `^`, and trace truth values with `not`, `and`, and `or`.", - "generator": "lecture-first-build", - "model": null - }, - "ai_common_questions": { - "status": "curated", - "bullets": [ - "a==1 or a==2 and b==1 or b==2 is evaluated as a==1 or (a==2 and b==1) or b==2" - ], - "items": [ - { - "id": "aiq-1", - "summary": "What is the result of (a//b)*b + a%b?", - "detail": "", - "extra": "Arithmetic operators", - "subtopic_id": "w1-operators-and-truth-core", - "subtopic_title": "Arithmetic, Comparison, and Boolean Operators" - }, - { - "id": "aiq-2", - "summary": "Boolean operator precedence: not > and > or", - "detail": "a==1 or a==2 and b==1 or b==2 is evaluated as a==1 or (a==2 and b==1) or b==2", - "extra": "", - "subtopic_id": "", - "subtopic_title": "" - } - ], - "generator": "lecture-first-build", - "model": null - }, - "key_points_to_remember": [ - { - "id": "kp-1", - "text": "a+b, a-b, a*b: standard. a/b: always returns float. a//b: floor division (highest integer <= result). a%b: remainder. a**b: exponentiation. NOTE: ^ is NOT exponentiation in Python (it is XOR). (a//b)*b + a%b == a always.", - "status": "curated", - "generator": "lecture-first-build", - "model": null, - "subtopic_id": "w1-operators-and-truth-core", - "subtopic_title": "Arithmetic, Comparison, and Boolean Operators", - "details": [ - { - "id": "kp-1-d1", - "kind": "example", - "title": "Floor division and modulo", - "code": "print(5 // 3, 5 % 3) # 1 2\nprint(-5 // 3, -5 % 3) # -2 1\nprint(5 // 2, 5 % 2) # 2 1\nprint(-5 // 2, -5 % 2) # -3 1" - } - ] }, { - "id": "kp-2", - "text": "==, !=, >, <, >=, <=. Always return True or False. Comparing floats can be tricky: 1.1+2.2 != 3.3 in Python due to floating-point precision. String/tuple/list comparison is element-by-element left to right; first differing element decides; if equal length and no differences, they are equal;", - "status": "curated", - "generator": "lecture-first-build", - "model": null, - "subtopic_id": "w1-operators-and-truth-core", - "subtopic_title": "Arithmetic, Comparison, and Boolean Operators", - "details": [ - { - "id": "kp-2-d1", - "kind": "example", - "title": "Float precision issue", - "code": "print(1.1 + 2.2 == 3.3) # False" - }, - { - "id": "kp-2-d2", - "kind": "example", - "title": "List/tuple comparison", - "code": "print([1, 2, 3] < [1, 2, 3, 0]) # True (shorter is less)\nprint([2] < [1, 2, 3, 0]) # False (2 > 1 at index 0)" - } - ] + "id": "cs-94491b4b00", + "week": 1, + "cell_index": null, + "cell_type": "code", + "source_type": "notebook", + "topic": "Objects and Names", + "subtopic_id": "w1-objects-and-names-core", + "subtopic_title": "Objects, Types, Mutability, Assignment, and Names", + "title": "mutable_immutable", + "source": "var_1 = (100, '100')\nid1 = id(var_1)\nvar_1[1] = '110'\nid2 = id(var_1)\nprint(id1 == id2)", + "outputs": [] }, { - "id": "kp-3", - "text": "x and y: True only if both True. x or y: False only if both False. not x: inverts. NOTE: && and || are Python operators but do something different (bitwise). Precedence: 'not' first, then 'and', then 'or'. Use parentheses to avoid confusion.", - "status": "curated", - "generator": "lecture-first-build", - "model": null, - "subtopic_id": "w1-operators-and-truth-core", - "subtopic_title": "Arithmetic, Comparison, and Boolean Operators", - "details": [ - { - "id": "kp-3-d1", - "kind": "example", - "title": "Precedence trap", - "code": "a=1; b=3\nprint(a==1 or a==2 and b==1 or b==2) # True (WRONG: and binds tighter)\nprint((a==1 or a==2) and (b==1 or b==2)) # False (CORRECT)" - } - ] - } - ], - "ai_examples": [ - { - "id": "ai-example-1", - "kind": "correct", - "title": "Floor division and modulo", - "code": "print(5 // 3, 5 % 3) # 1 2\nprint(-5 // 3, -5 % 3) # -2 1\nprint(5 // 2, 5 % 2) # 2 1\nprint(-5 // 2, -5 % 2) # -3 1", - "why": "a+b, a-b, a*b: standard. a/b: always returns float. a//b: floor division (highest integer <= result). a%b: remainder. a**b: exponentiation. NOTE: ^ is NOT exponentiation in Python (it is XOR). (a//b)*b + a%b == a always.", - "output": "", - "status": "curated", - "subtopic_id": "w1-operators-and-truth-core", - "subtopic_title": "Arithmetic, Comparison, and Boolean Operators" - }, - { - "id": "ai-example-2", - "kind": "correct", - "title": "Float precision issue", - "code": "print(1.1 + 2.2 == 3.3) # False", - "why": "==, !=, >, <, >=, <=. Always return True or False. Comparing floats can be tricky: 1.1+2.2 != 3.3 in Python due to floating-point precision. String/tuple/list comparison is element-by-element left to right; first differing element decides; if equal length and no differences, they are equal;", - "output": "", - "status": "curated", - "subtopic_id": "w1-operators-and-truth-core", - "subtopic_title": "Arithmetic, Comparison, and Boolean Operators" - }, - { - "id": "ai-example-3", - "kind": "correct", - "title": "List/tuple comparison", - "code": "print([1, 2, 3] < [1, 2, 3, 0]) # True (shorter is less)\nprint([2] < [1, 2, 3, 0]) # False (2 > 1 at index 0)", - "why": "==, !=, >, <, >=, <=. Always return True or False. Comparing floats can be tricky: 1.1+2.2 != 3.3 in Python due to floating-point precision. String/tuple/list comparison is element-by-element left to right; first differing element decides; if equal length and no differences, they are equal;", - "output": "", - "status": "curated", - "subtopic_id": "w1-operators-and-truth-core", - "subtopic_title": "Arithmetic, Comparison, and Boolean Operators" - }, - { - "id": "ai-example-4", - "kind": "correct", - "title": "Precedence trap", - "code": "a=1; b=3\nprint(a==1 or a==2 and b==1 or b==2) # True (WRONG: and binds tighter)\nprint((a==1 or a==2) and (b==1 or b==2)) # False (CORRECT)", - "why": "x and y: True only if both True. x or y: False only if both False. not x: inverts. NOTE: && and || are Python operators but do something different (bitwise). Precedence: 'not' first, then 'and', then 'or'. Use parentheses to avoid confusion.", - "output": "", - "status": "curated", - "subtopic_id": "w1-operators-and-truth-core", - "subtopic_title": "Arithmetic, Comparison, and Boolean Operators" - }, - { - "id": "ai-example-5", - "kind": "correct", - "title": "arithmetic_operators", - "code": "print(5//2, 5%2)", - "why": "", - "output": "2 1", - "status": "curated", - "subtopic_id": "w1-operators-and-truth-core", - "subtopic_title": "Arithmetic, Comparison, and Boolean Operators" - }, - { - "id": "ai-example-6", - "kind": "correct", - "title": "arithmetic_operators", - "code": "print(4 + 3)\nprint(4 - 3)\nprint(4 * 3)\nprint(4 / 3)\nprint(4 / 2)\nprint(4 ** 3)", - "why": "", - "output": "7\n1\n12\n1.3333333333333333\n2.0\n64", - "status": "curated", - "subtopic_id": "w1-operators-and-truth-core", - "subtopic_title": "Arithmetic, Comparison, and Boolean Operators" - }, - { - "id": "ai-example-7", - "kind": "correct", - "title": "arithmetic_operators", - "code": "print(5 // 3, 5 % 3)\nprint(-5 // 3, -5 % 3)\nprint(5 // 2, 5 % 2)\nprint(-5 // 2, -5 % 2)", - "why": "", - "output": "1 2\n-2 1\n2 1\n-3 1", - "status": "curated", - "subtopic_id": "w1-operators-and-truth-core", - "subtopic_title": "Arithmetic, Comparison, and Boolean Operators" - }, - { - "id": "ai-example-8", - "kind": "correct", - "title": "`==` versus `is`", - "code": "#\nimport random # The random module that can be used to generate pseudo-random numbers is part of the standard Python installation\n # but the name has still to be importent\na = random.randint(3, 9) # This generates an integer between 3 and 9 (both included), it is given the name 'a'\nb = random.randint(3, 9) # # This generates an integer between 3 and 9 (both included), it is given the name 'b'\nprint (a, b)\nprint(a==(a/b)*b + a%b) # == compares what is left of it to what is right of it and evaluates to True if both sides evaluate to the same value", - "why": "`==` compares value equality; `is` compares whether two names refer to the same object.", - "output": "8 4\nTrue", - "status": "curated", - "subtopic_id": "w1-operators-and-truth-core", - "subtopic_title": "Arithmetic, Comparison, and Boolean Operators" + "id": "cs-33e88a778b", + "week": 1, + "cell_index": null, + "cell_type": "code", + "source_type": "notebook", + "topic": "Objects and Names", + "subtopic_id": "w1-objects-and-names-core", + "subtopic_title": "Objects, Types, Mutability, Assignment, and Names", + "title": "identity_id", + "source": "var_1 = 321\nprint(id(var_1))\nvar_2 = 321\nprint(id(var_2))\nprint(var_1 == var_2)\nprint(var_1 is var_2)", + "outputs": [] } ], "recommended_ids": [ - "ks-03c874b8bb", - "ks-c0135e2a4a", - "ks-c815ffe1d5", - "cs-7eb8617d28", - "cs-3cb4b8e8f9", - "cs-266616a010", - "cs-4f8a5f420b" - ] - } - }, - { - "id": "w1-sequences-and-access", - "topic": "Sequences and Access", - "canonical_topic": "w1-sequences-and-access", - "weeks": [ - 1 - ], - "week_id": "week-1", - "topic_meta": { - "week": 1, - "week_id": "week-1", - "week_title": "Week 1", - "topic_id": "w1-sequences-and-access", - "topic_title": "Sequences and Access", - "topic_order": 4 + "exam-intro_python_sample_final_24_25-13-w1-objects-and-names", + "exam-trial-final-exam-py22-1-w1-objects-and-names", + "exam-Test Resit - Introduction to Python - 22/23-3-w1-objects-and-names", + "exam-Trial final - Introduction to Python - 22/23-1-w1-objects-and-names", + "exam-Trial final exam Introduction to Python-3-w1-objects-and-names", + "exam-trial_midterm-1-w1-objects-and-names", + "exam-trial_midterm-3-w1-objects-and-names", + "exam-trial_midterm-4-w1-objects-and-names", + "exam-trial_midterm-7-w1-objects-and-names", + "ks-e88d0a8060", + "ks-eae9bf47dd", + "ks-61c5deec4a", + "ks-cb3a9e3fd2" + ], + "homework_snippets": [], + "homework_recommended_ids": [] }, "subtopics": [ { - "id": "w1-sequences-and-access-core", - "title": "Indexing, Slicing, and range()", + "id": "w1-objects-and-names-core", + "title": "Objects, Types, Mutability, Assignment, and Names", "order": 1, - "summary": "Use `seq[start:stop:step]` with stop excluded. Negative indices count from the end, and `range(start, stop, step)` follows the same stop-excluded rule.", + "summary": "Objects have identity, type, and value. Names bind to objects; rebinding changes the name, while mutation only matters for mutable objects.", "item_ids": { "lecture_snippet_ids": [ - "ks-685cd3d828", - "ks-be78ccac04" + "ks-e88d0a8060", + "ks-eae9bf47dd", + "ks-61c5deec4a", + "ks-cb3a9e3fd2", + "ks-d79a1899f6", + "ks-6f41148083", + "ks-0153de2f70", + "ks-df3b849d59", + "ks-419e787b39" ], "exam_question_ids": [ - "exam-extra_practice-6-w1-sequences-and-access" + "exam-trial_midterm-1-w1-objects-and-names", + "exam-trial_midterm-3-w1-objects-and-names", + "exam-trial_midterm-4-w1-objects-and-names", + "exam-trial_midterm-7-w1-objects-and-names", + "exam-trial_midterm-9-w1-objects-and-names", + "exam-trial_midterm-11-w1-objects-and-names", + "exam-trial_midterm-12-w1-objects-and-names", + "exam-trial_midterm-14-w1-objects-and-names", + "exam-trial_midterm-15-w1-objects-and-names", + "exam-trial_midterm-16-w1-objects-and-names", + "exam-trial_midterm-18-w1-objects-and-names", + "exam-trial_midterm-20-w1-objects-and-names", + "exam-trial_midterm-21-w1-objects-and-names", + "exam-trial_midterm-22-w1-objects-and-names", + "exam-trial_midterm-24-w1-objects-and-names", + "exam-midterm_2023-4-w1-objects-and-names", + "exam-midterm_2024-4-w1-objects-and-names", + "exam-midterm_2024-6-w1-objects-and-names", + "exam-extra_practice-11-w1-objects-and-names", + "exam-Trial final - Introduction to Python - 22/23-1-w1-objects-and-names", + "exam-trial-final-exam-py22-1-w1-objects-and-names", + "exam-Test Resit - Introduction to Python - 22/23-3-w1-objects-and-names", + "exam-intro_python_sample_final_24_25-13-w1-objects-and-names", + "exam-Trial final exam Introduction to Python-3-w1-objects-and-names" ], "notebook_snippet_ids": [ - "cs-60dd1a8d2c", - "cs-0af6442b99", - "cs-85d755c5e8", - "cs-8a4ee4419d", - "cs-7ac6156d67", - "cs-15d46dcc2c", - "cs-ab9dc084b6", - "cs-59038bcffa" + "cs-cd4f0b5c6e", + "cs-b65f3408e3", + "cs-d185f0c824", + "cs-04169579a8", + "cs-58c37dfe80", + "cs-ef4e6233fe", + "cs-94491b4b00", + "cs-33e88a778b" ], "example_ids": [ "ai-example-1", "ai-example-2", + "ai-example-3", "ai-example-4", "ai-example-5", "ai-example-6", - "ai-example-7" + "ai-example-7", + "ai-example-8", + "manual-objects-aliasing" ], "key_point_ids": [ "kp-1", - "kp-2" + "kp-2", + "kp-3", + "kp-4", + "kp-5", + "kp-6", + "kp-manual-aliasing-copy", + "kp-7", + "kp-8", + "kp-9" ] } } ], - "exam_stats": { - "total_hits": 1, - "by_exam": { - "extra_practice": 1 - }, - "coverage_count": 1 + "topic": "Objects and Names", + "topic_meta": { + "week": 1, + "week_id": "week-1", + "week_title": "Week 1", + "topic_id": "w1-objects-and-names", + "topic_title": "Objects and Names", + "topic_order": 2 }, - "related_topics": [ - "Indexing, Slicing, and range()" - ], "trap_patterns": [ { - "pattern": "str.upper() / string methods don't modify in place", - "trap": "s.upper() returns a new string; s is unchanged. Must do s = s.upper()", + "pattern": "Slicing creates a NEW object", + "trap": "l2=l1 vs l2=l1[:] — l2=l1 shares the SAME object, slicing creates independent copy", "weeks": [ 1 ], "appears_in_exams": [ "trial_midterm", - "midterm_2023" + "midterm_2023", + "midterm_2024", + "extra_practice" ] }, { - "pattern": "range() and slicing both exclusive at stop", - "trap": "range(1,10,3)→[1,4,7] not including 10; l[2:7] goes up to but not including index 7", + "pattern": "Mutable default argument", + "trap": "def f(lst=[]): — the [] is created ONCE at def time and persists across calls. Fix: use None and create inside function", "weeks": [ - 1, - 2 + 3 + ], + "appears_in_exams": [ + "trial_midterm", + "midterm_2024" + ] + }, + { + "pattern": "Mutable parameter sharing", + "trap": "When mutable object passed as argument, parameter and argument point to SAME object — mutations inside function affect original", + "weeks": [ + 3 + ], + "appears_in_exams": [ + "midterm_2023", + "extra_practice" + ] + }, + { + "pattern": "UnboundLocalError", + "trap": "If a name appears on the left side of assignment ANYWHERE in a function, Python treats it as local THROUGHOUT the function body — even before the assignment line", + "weeks": [ + 3 ], "appears_in_exams": [ "trial_midterm", @@ -2182,227 +1607,313 @@ ] }, { - "pattern": "Negative slicing with step=-2", - "trap": "l[::-2] starts from last element going backwards with step 2. l[::2][::-1] first takes every other starting from 0, then reverses — different result", + "pattern": "Tuple inside mutable container can be mutated via the mutable part", + "trap": "t=(1,[2,3],4); t[1].append(5) works — tuple immutable means you can't reassign t[1], but the list t[1] refers to IS mutable", "weeks": [ 1 ], "appears_in_exams": [ + "midterm_2024" + ] + }, + { + "pattern": "Wrong bracket type errors", + "trap": "print[1] → TypeError 'not subscriptable'; l1(1) → TypeError 'not callable'", + "weeks": [ + 3 + ], + "appears_in_exams": [ + "trial_midterm" + ] + }, + { + "pattern": "map/filter return iterables, not lists", + "trap": "list(map(lambda x: x*2, l)) — must wrap in list(). Without it: ", + "weeks": [ + 3 + ], + "appears_in_exams": [ + "trial_midterm", "extra_practice" ] + }, + { + "pattern": "1 + True = 2 (bool is subclass of int)", + "trap": "True==1, False==0 in numeric contexts. type(True)==int is False but isinstance(True,int) is True", + "weeks": [ + 2 + ], + "appears_in_exams": [ + "midterm_2023" + ] } ], - "sections": { - "lecture_snippets": [ - { - "id": "ks-685cd3d828", - "week": 1, - "source": "materials/lectures/Lecture Week 1.md", - "source_type": "lecture", - "topic": "Sequences and Access", - "subtopic_id": "w1-sequences-and-access-core", - "subtopic_title": "Indexing, Slicing, and range()", - "title": "Indexing", - "explanation": "Forward: 0, 1, 2, ... len-1. Backward: -1 (last), -2 (second to last), ..., -len (first). l1[0] == l1[-len(l1)]", - "code_examples": [] + "week_id": "week-1", + "weeks": [ + 1 + ] + }, + { + "id": "w1-operators-and-truth", + "topic": "Operators and Truth", + "canonical_topic": "w1-operators-and-truth", + "weeks": [ + 1 + ], + "week_id": "week-1", + "topic_meta": { + "week": 1, + "week_id": "week-1", + "week_title": "Week 1", + "topic_id": "w1-operators-and-truth", + "topic_title": "Operators and Truth", + "topic_order": 3 + }, + "subtopics": [ + { + "id": "w1-operators-and-truth-core", + "title": "Arithmetic, Comparison, and Boolean Operators", + "order": 1, + "summary": "Know arithmetic, comparison, and boolean precedence. Distinguish `/` vs `//`, `**` vs `^`, and trace truth values with `not`, `and`, and `or`.", + "item_ids": { + "lecture_snippet_ids": [ + "ks-03c874b8bb", + "ks-c0135e2a4a", + "ks-c815ffe1d5" + ], + "exam_question_ids": [], + "notebook_snippet_ids": [ + "cs-7eb8617d28", + "cs-3cb4b8e8f9", + "cs-266616a010", + "cs-4f8a5f420b", + "cs-5edb9a0b07", + "cs-eb7fa31fd3", + "cs-4b73ab2680" + ], + "example_ids": [ + "ai-example-1", + "ai-example-2", + "ai-example-3", + "ai-example-4", + "ai-example-5", + "ai-example-6", + "ai-example-7", + "ai-example-8" + ], + "key_point_ids": [ + "kp-1", + "kp-2" + ] + } + } + ], + "exam_stats": { + "total_hits": 0, + "by_exam": {}, + "coverage_count": 0 + }, + "related_topics": [ + "Arithmetic, Comparison, and Boolean Operators" + ], + "trap_patterns": [ + { + "pattern": "Boolean operator precedence: not > and > or", + "trap": "a==1 or a==2 and b==1 or b==2 is evaluated as a==1 or (a==2 and b==1) or b==2", + "weeks": [ + 1, + 2 + ], + "appears_in_exams": [ + "midterm_2023", + "extra_practice" + ] + } + ], + "sections": { + "lecture_snippets": [ + { + "id": "ks-03c874b8bb", + "week": 1, + "source": "materials/lectures/Lecture Week 1.md", + "source_type": "lecture", + "topic": "Operators and Truth", + "subtopic_id": "w1-operators-and-truth-core", + "subtopic_title": "Arithmetic, Comparison, and Boolean Operators", + "title": "Arithmetic operators", + "explanation": "a+b, a-b, a*b: standard. a/b: always returns float. a//b: floor division (highest integer <= result). a%b: remainder. a**b: exponentiation. NOTE: ^ is NOT exponentiation in Python (it is XOR). (a//b)*b + a%b == a always.", + "code_examples": [ + { + "description": "Floor division and modulo", + "code": "print(5 // 3, 5 % 3) # 1 2\nprint(-5 // 3, -5 % 3) # -2 1\nprint(5 // 2, 5 % 2) # 2 1\nprint(-5 // 2, -5 % 2) # -3 1" + } + ] }, { - "id": "ks-be78ccac04", + "id": "ks-c0135e2a4a", "week": 1, "source": "materials/lectures/Lecture Week 1.md", "source_type": "lecture", - "topic": "Sequences and Access", - "subtopic_id": "w1-sequences-and-access-core", - "subtopic_title": "Indexing, Slicing, and range()", - "title": "range()", - "explanation": "range(start, stop, step). start default=0, step default=1. Stop is NOT inclusive. Works like slicing but defaults differ slightly.", + "topic": "Operators and Truth", + "subtopic_id": "w1-operators-and-truth-core", + "subtopic_title": "Arithmetic, Comparison, and Boolean Operators", + "title": "Comparison operators", + "explanation": "==, !=, >, <, >=, <=. Always return True or False. Comparing floats can be tricky: 1.1+2.2 != 3.3 in Python due to floating-point precision. String/tuple/list comparison is element-by-element left to right; first differing element decides; if equal length and no differences, they are equal; shorter sequence is 'less than' longer if all elements match up to shorter length.", "code_examples": [ { - "description": "range examples", - "code": "print(list(range(6))) # [0, 1, 2, 3, 4, 5]\nprint(list(range(3,6))) # [3, 4, 5]\nprint(list(range(3,6,2))) # [3, 5]" + "description": "Float precision issue", + "code": "print(1.1 + 2.2 == 3.3) # False" + }, + { + "description": "List/tuple comparison", + "code": "print([1, 2, 3] < [1, 2, 3, 0]) # True (shorter is less)\nprint([2] < [1, 2, 3, 0]) # False (2 > 1 at index 0)" } ] - } - ], - "exam_questions": [ + }, { - "id": "exam-extra_practice-6-w1-sequences-and-access", - "exam_label": "extra_practice", - "exam_source": "materials/exams/Midterm Extra Practice.txt", - "year": "unknown", - "number": 6, + "id": "ks-c815ffe1d5", "week": 1, - "topic": "slicing / negative step", - "subtopic_id": "w1-sequences-and-access-core", - "subtopic_title": "Indexing, Slicing, and range()", - "question": "numbers = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]\n\nWhich of the following lines of code will NOT create a list with the name subset, and the value [10, 8, 6, 4, 2]?", - "code_context": "", - "options": { - "a": "subset = numbers[-1::-2]", - "b": "subset = numbers[::-2]", - "c": "subset = numbers[::-1][::2]", - "d": "subset = numbers[::2][::-1]" - }, - "correct": "d", - "explanation": "a: starts at -1 (10), step -2: [10,8,6,4,2]. Correct. b: [::-2] starts at last (10), step -2: [10,8,6,4,2]. Correct. c: [::-1] reverses to [10,9,8,7,6,5,4,3,2,1], then [::2] takes every 2nd: [10,8,6,4,2]. Correct. d: [::2] gives [1,3,5,7,9], then [::-1] reverses: [9,7,5,3,1]. This does NOT give [10,8,6,4,2]. Correct answer (the one that does NOT work): d." + "source": "materials/lectures/Lecture Week 1.md", + "source_type": "lecture", + "topic": "Operators and Truth", + "subtopic_id": "w1-operators-and-truth-core", + "subtopic_title": "Arithmetic, Comparison, and Boolean Operators", + "title": "Boolean operators", + "explanation": "x and y: True only if both True. x or y: False only if both False. not x: inverts. NOTE: && and || are Python operators but do something different (bitwise). Precedence: 'not' first, then 'and', then 'or'. Use parentheses to avoid confusion.", + "code_examples": [ + { + "description": "Precedence trap", + "code": "a=1; b=3\nprint(a==1 or a==2 and b==1 or b==2) # True (WRONG: and binds tighter)\nprint((a==1 or a==2) and (b==1 or b==2)) # False (CORRECT)" + } + ] } ], + "exam_questions": [], "notebook_snippets": [ { - "id": "cs-60dd1a8d2c", + "id": "cs-7eb8617d28", "week": 1, "cell_index": null, "cell_type": "code", "source_type": "notebook", - "topic": "Sequences and Access", - "subtopic_id": "w1-sequences-and-access-core", - "subtopic_title": "Indexing, Slicing, and range()", - "title": "print(\"This is a string\")", - "source": "print(\"This is a string\")\nprint('This is another string')", - "outputs": [] + "topic": "Operators and Truth", + "subtopic_id": "w1-operators-and-truth-core", + "subtopic_title": "Arithmetic, Comparison, and Boolean Operators", + "title": "arithmetic_operators", + "source": "print(5//2, 5%2)", + "outputs": [ + "2 1" + ] }, { - "id": "cs-0af6442b99", + "id": "cs-3cb4b8e8f9", "week": 1, "cell_index": null, "cell_type": "code", "source_type": "notebook", - "topic": "Sequences and Access", - "subtopic_id": "w1-sequences-and-access-core", - "subtopic_title": "Indexing, Slicing, and range()", - "title": "strings_quotes", - "source": "print('This gives an error\")\nprint(\"This gives an error')", - "outputs": [] + "topic": "Operators and Truth", + "subtopic_id": "w1-operators-and-truth-core", + "subtopic_title": "Arithmetic, Comparison, and Boolean Operators", + "title": "arithmetic_operators", + "source": "print(4 + 3)\nprint(4 - 3)\nprint(4 * 3)\nprint(4 / 3)\nprint(4 / 2)\nprint(4 ** 3)", + "outputs": [ + "7\n1\n12\n1.3333333333333333\n2.0\n64" + ] }, { - "id": "cs-85d755c5e8", + "id": "cs-266616a010", "week": 1, "cell_index": null, "cell_type": "code", "source_type": "notebook", - "topic": "Sequences and Access", - "subtopic_id": "w1-sequences-and-access-core", - "subtopic_title": "Indexing, Slicing, and range()", - "title": "strings_quotes", - "source": "print(\"This gives no ' error\")\nprint('This gives no \" error')", - "outputs": [] + "topic": "Operators and Truth", + "subtopic_id": "w1-operators-and-truth-core", + "subtopic_title": "Arithmetic, Comparison, and Boolean Operators", + "title": "arithmetic_operators", + "source": "print(5 // 3, 5 % 3)\nprint(-5 // 3, -5 % 3)\nprint(5 // 2, 5 % 2)\nprint(-5 // 2, -5 % 2)", + "outputs": [ + "1 2\n-2 1\n2 1\n-3 1" + ] }, { - "id": "cs-8a4ee4419d", + "id": "cs-4f8a5f420b", "week": 1, "cell_index": null, "cell_type": "code", "source_type": "notebook", - "topic": "Sequences and Access", - "subtopic_id": "w1-sequences-and-access-core", - "subtopic_title": "Indexing, Slicing, and range()", - "title": "a = 'This is a string'", - "source": "a = 'This is a string' \nb = \"This is another string\"\nprint(a)\nprint(b)\nprint(a,b)", - "outputs": [] + "topic": "Operators and Truth", + "subtopic_id": "w1-operators-and-truth-core", + "subtopic_title": "Arithmetic, Comparison, and Boolean Operators", + "title": "arithmetic_operators", + "source": "#\nimport random # The random module that can be used to generate pseudo-random numbers is part of the standard Python installation\n # but the name has still to be importent\na = random.randint(3, 9) # This generates an integer between 3 and 9 (both included), it is given the name 'a'\nb = random.randint(3, 9) # # This generates an integer between 3 and 9 (both included), it is given the name 'b'\nprint (a, b)\nprint(a==(a/b)*b + a%b) # == compares what is left of it to what is right of it and evaluates to True if both sides evaluate to the same value", + "outputs": [ + "8 4\nTrue" + ] }, { - "id": "cs-7ac6156d67", + "id": "cs-5edb9a0b07", "week": 1, "cell_index": null, "cell_type": "code", "source_type": "notebook", - "topic": "Sequences and Access", - "subtopic_id": "w1-sequences-and-access-core", - "subtopic_title": "Indexing, Slicing, and range()", - "title": "a = 'This is a string'; b = 6; c = 0.0", - "source": "#\na = 'This is a string'; b = 6; c = 0.0 \nprint(f\"We know {a =}, {b= }, and {c = }\")", + "topic": "Operators and Truth", + "subtopic_id": "w1-operators-and-truth-core", + "subtopic_title": "Arithmetic, Comparison, and Boolean Operators", + "title": "comparison_operators", + "source": "print(1.1, 2.2, 1.1 + 2.2 == 3.3)", "outputs": [] }, { - "id": "cs-15d46dcc2c", + "id": "cs-eb7fa31fd3", "week": 1, "cell_index": null, "cell_type": "code", "source_type": "notebook", - "topic": "Sequences and Access", - "subtopic_id": "w1-sequences-and-access-core", - "subtopic_title": "Indexing, Slicing, and range()", - "title": "slicing", - "source": "l1 = ['a', 'b']\nl2 = l1\nl2[-1] = 'c'\nprint(l1 == l3)\nl3 = l1[::]\nl3[-1] = 'c'\nprint(l1 == l3)", + "topic": "Operators and Truth", + "subtopic_id": "w1-operators-and-truth-core", + "subtopic_title": "Arithmetic, Comparison, and Boolean Operators", + "title": "comparison_operators", + "source": "print(3 == 2)\nprint(3 > 3)\nprint(3 < 4)\nprint(3 >= 2)\nprint(3 <= 3)\nprint(3 != 4)", "outputs": [] }, { - "id": "cs-ab9dc084b6", + "id": "cs-4b73ab2680", "week": 1, "cell_index": null, "cell_type": "code", "source_type": "notebook", - "topic": "Sequences and Access", - "subtopic_id": "w1-sequences-and-access-core", - "subtopic_title": "Indexing, Slicing, and range()", - "title": "a = 'This is a string'", - "source": "a = 'This is a string' \nb = \"This is another string\"\nprint(a + b)\nprint(\"First string: '\" + a + \"', Second string: '\" + b + \"'.\")", - "outputs": [] - }, - { - "id": "cs-59038bcffa", - "week": 1, - "cell_index": null, - "cell_type": "code", - "source_type": "notebook", - "topic": "Sequences and Access", - "subtopic_id": "w1-sequences-and-access-core", - "subtopic_title": "Indexing, Slicing, and range()", - "title": "strings_fstrings", - "source": "a = 'This is a string' \nb = \"This is another string\"\nprint(f\"First string: '{a}', Second string: '{b}'.\")\nprint(\"First string: '{a}', Second string: '{b}'.\")", + "topic": "Operators and Truth", + "subtopic_id": "w1-operators-and-truth-core", + "subtopic_title": "Arithmetic, Comparison, and Boolean Operators", + "title": "comparison_operators", + "source": "print([1, 2, 3] < [1, 2, 3, 0])\nprint([2] < [1, 2, 3, 0])\nprint((1, 2, 3, 0) < (1, 2, 3))\nprint((2,) >= (1, 2, 3, 0))\nprint('abc' < 'abc ')\nprint('b' < 'abc ')\nprint('123' < '123 ')\nprint('2' < '123 ')", "outputs": [] } ], "ai_summary": { "status": "curated", - "content": "Use `seq[start:stop:step]` with stop excluded. Negative indices count from the end, and `range(start, stop, step)` follows the same stop-excluded rule.", + "content": "Know arithmetic, comparison, and boolean precedence. Distinguish `/` vs `//`, `**` vs `^`, and trace truth values with `not`, `and`, and `or`.", "generator": "lecture-first-build", "model": null }, "ai_common_questions": { "status": "curated", "bullets": [ - "s.upper() returns a new string; s is unchanged. Must do s = s.upper()", - "range(1,10,3)→[1,4,7] not including 10; l[2:7] goes up to but not including index 7", - "l[::-2] starts from last element going backwards with step 2. l[::2][::-1] first takes every other starting from 0, then reverses — different result" + "a==1 or a==2 and b==1 or b==2 is evaluated as a==1 or (a==2 and b==1) or b==2" ], "items": [ { "id": "aiq-1", - "summary": "Slicing / mutability", - "detail": "Track which names point to the same object and which slice creates a copy before the mutation happens.", - "extra": "Slicing / mutability", - "subtopic_id": "w1-sequences-and-access-core", - "subtopic_title": "Indexing, Slicing, and range()" + "summary": "What is the result of (a//b)*b + a%b?", + "detail": "", + "extra": "Arithmetic operators", + "subtopic_id": "w1-operators-and-truth-core", + "subtopic_title": "Arithmetic, Comparison, and Boolean Operators" }, { "id": "aiq-2", - "summary": "Slicing negative step", - "detail": "Read the slice as `start:stop:step`; with a negative step Python walks right-to-left and still excludes the stop position.", - "extra": "Slicing negative step", - "subtopic_id": "w1-sequences-and-access-core", - "subtopic_title": "Indexing, Slicing, and range()" - }, - { - "id": "aiq-3", - "summary": "numbers = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]", - "detail": "a: starts at -1 (10), step -2: [10,8,6,4,2]. Correct. b: [::-2] starts at last (10), step -2: [10,8,6,4,2]. Correct. c: [::-1] reverses to [10,9,8,7,6,5,4,3,2,1], then [::2] takes every 2nd: [10,8,6,4,2]. Correct. d: [::2] gives [1,3,5,7,9], then [::-1] reverses: [9,7,5,3,1]. This does NOT give [10,8,6,4,2].", - "extra": "Exam • extra_practice • Q6", - "subtopic_id": "w1-sequences-and-access-core", - "subtopic_title": "Indexing, Slicing, and range()" - }, - { - "id": "aiq-5", - "summary": "str.upper() / string methods don't modify in place", - "detail": "s.upper() returns a new string; s is unchanged. Must do s = s.upper()", - "extra": "", - "subtopic_id": "", - "subtopic_title": "" - }, - { - "id": "aiq-6", - "summary": "range() and slicing both exclusive at stop", - "detail": "range(1,10,3)→[1,4,7] not including 10; l[2:7] goes up to but not including index 7", + "summary": "Boolean operator precedence: not > and > or", + "detail": "a==1 or a==2 and b==1 or b==2 is evaluated as a==1 or (a==2 and b==1) or b==2", "extra": "", "subtopic_id": "", "subtopic_title": "" @@ -2414,500 +1925,487 @@ "key_points_to_remember": [ { "id": "kp-1", - "text": "Negative indices count from the end: `seq[-1]` is last and `seq[-len(seq)]` is first.", + "text": "a+b, a-b, a*b: standard. a/b: always returns float. a//b: floor division (highest integer <= result). a%b: remainder. a**b: exponentiation. NOTE: ^ is NOT exponentiation in Python (it is XOR). (a//b)*b + a%b == a always.", "status": "curated", "generator": "lecture-first-build", "model": null, - "subtopic_id": "w1-sequences-and-access-core", - "subtopic_title": "Indexing, Slicing, and range()", + "subtopic_id": "w1-operators-and-truth-core", + "subtopic_title": "Arithmetic, Comparison, and Boolean Operators", "details": [ { "id": "kp-1-d1", - "kind": "table", - "title": "Dense reference table", - "table": { - "headers": [ - "Pattern", - "Meaning", - "Example" - ], - "rows": [ - [ - "seq[i]", - "single element", - "x[-1]" - ], - [ - "seq[a:b]", - "start inclusive, stop exclusive", - "x[1:4]" - ], - [ - "seq[::-1]", - "reverse copy", - "x[::-1]" - ], - [ - "seq[::2]", - "step through every other item", - "x[::2]" - ] - ] - } + "kind": "example", + "title": "Floor division and modulo", + "code": "print(5 // 3, 5 % 3) # 1 2\nprint(-5 // 3, -5 % 3) # -2 1\nprint(5 // 2, 5 % 2) # 2 1\nprint(-5 // 2, -5 % 2) # -3 1" } ] }, { "id": "kp-2", - "text": "`range(start, stop, step)` excludes `stop`; defaults are `start=0` and `step=1`, just like slicing excludes the stop index.", + "text": "==, !=, >, <, >=, <=. Always return True or False. Comparing floats can be tricky: 1.1+2.2 != 3.3 in Python due to floating-point precision. String/tuple/list comparison is element-by-element left to right; first differing element decides; if equal length and no differences, they are equal;", "status": "curated", "generator": "lecture-first-build", "model": null, - "subtopic_id": "w1-sequences-and-access-core", - "subtopic_title": "Indexing, Slicing, and range()", + "subtopic_id": "w1-operators-and-truth-core", + "subtopic_title": "Arithmetic, Comparison, and Boolean Operators", "details": [ { "id": "kp-2-d1", "kind": "example", - "title": "range examples", - "code": "print(list(range(6))) # [0, 1, 2, 3, 4, 5]\nprint(list(range(3,6))) # [3, 4, 5]\nprint(list(range(3,6,2))) # [3, 5]" + "title": "Float precision issue", + "code": "print(1.1 + 2.2 == 3.3) # False" + }, + { + "id": "kp-2-d2", + "kind": "example", + "title": "List/tuple comparison", + "code": "print([1, 2, 3] < [1, 2, 3, 0]) # True (shorter is less)\nprint([2] < [1, 2, 3, 0]) # False (2 > 1 at index 0)" } ] }, { "id": "kp-3", - "text": "Pattern to remember: subset = numbers[::2][::-1]", + "text": "x and y: True only if both True. x or y: False only if both False. not x: inverts. NOTE: && and || are Python operators but do something different (bitwise). Precedence: 'not' first, then 'and', then 'or'. Use parentheses to avoid confusion.", "status": "curated", "generator": "lecture-first-build", "model": null, - "subtopic_id": "w1-sequences-and-access-core", - "subtopic_title": "Indexing, Slicing, and range()", - "details": [] + "subtopic_id": "w1-operators-and-truth-core", + "subtopic_title": "Arithmetic, Comparison, and Boolean Operators", + "details": [ + { + "id": "kp-3-d1", + "kind": "example", + "title": "Precedence trap", + "code": "a=1; b=3\nprint(a==1 or a==2 and b==1 or b==2) # True (WRONG: and binds tighter)\nprint((a==1 or a==2) and (b==1 or b==2)) # False (CORRECT)" + } + ] } ], "ai_examples": [ { "id": "ai-example-1", "kind": "correct", - "title": "range() output patterns", - "code": "print(list(range(6))) # [0, 1, 2, 3, 4, 5]\nprint(list(range(3,6))) # [3, 4, 5]\nprint(list(range(3,6,2))) # [3, 5]", - "why": "`range(start, stop, step)` excludes `stop`; defaults are `start=0` and `step=1`, just like slicing excludes the stop index.", + "title": "Floor division and modulo", + "code": "print(5 // 3, 5 % 3) # 1 2\nprint(-5 // 3, -5 % 3) # -2 1\nprint(5 // 2, 5 % 2) # 2 1\nprint(-5 // 2, -5 % 2) # -3 1", + "why": "a+b, a-b, a*b: standard. a/b: always returns float. a//b: floor division (highest integer <= result). a%b: remainder. a**b: exponentiation. NOTE: ^ is NOT exponentiation in Python (it is XOR). (a//b)*b + a%b == a always.", "output": "", "status": "curated", - "subtopic_id": "w1-sequences-and-access-core", - "subtopic_title": "Indexing, Slicing, and range()" + "subtopic_id": "w1-operators-and-truth-core", + "subtopic_title": "Arithmetic, Comparison, and Boolean Operators" }, { "id": "ai-example-2", "kind": "correct", - "title": "print(\"This is a string\")", - "code": "print(\"This is a string\")\nprint('This is another string')", - "why": "", + "title": "Float precision issue", + "code": "print(1.1 + 2.2 == 3.3) # False", + "why": "==, !=, >, <, >=, <=. Always return True or False. Comparing floats can be tricky: 1.1+2.2 != 3.3 in Python due to floating-point precision. String/tuple/list comparison is element-by-element left to right; first differing element decides; if equal length and no differences, they are equal;", "output": "", "status": "curated", - "subtopic_id": "w1-sequences-and-access-core", - "subtopic_title": "Indexing, Slicing, and range()" + "subtopic_id": "w1-operators-and-truth-core", + "subtopic_title": "Arithmetic, Comparison, and Boolean Operators" + }, + { + "id": "ai-example-3", + "kind": "correct", + "title": "List/tuple comparison", + "code": "print([1, 2, 3] < [1, 2, 3, 0]) # True (shorter is less)\nprint([2] < [1, 2, 3, 0]) # False (2 > 1 at index 0)", + "why": "==, !=, >, <, >=, <=. Always return True or False. Comparing floats can be tricky: 1.1+2.2 != 3.3 in Python due to floating-point precision. String/tuple/list comparison is element-by-element left to right; first differing element decides; if equal length and no differences, they are equal;", + "output": "", + "status": "curated", + "subtopic_id": "w1-operators-and-truth-core", + "subtopic_title": "Arithmetic, Comparison, and Boolean Operators" }, { "id": "ai-example-4", "kind": "correct", - "title": "String quotes and escaping", - "code": "print(\"This gives no ' error\")\nprint('This gives no \" error')", - "why": "", + "title": "Precedence trap", + "code": "a=1; b=3\nprint(a==1 or a==2 and b==1 or b==2) # True (WRONG: and binds tighter)\nprint((a==1 or a==2) and (b==1 or b==2)) # False (CORRECT)", + "why": "x and y: True only if both True. x or y: False only if both False. not x: inverts. NOTE: && and || are Python operators but do something different (bitwise). Precedence: 'not' first, then 'and', then 'or'. Use parentheses to avoid confusion.", "output": "", "status": "curated", - "subtopic_id": "w1-sequences-and-access-core", - "subtopic_title": "Indexing, Slicing, and range()" + "subtopic_id": "w1-operators-and-truth-core", + "subtopic_title": "Arithmetic, Comparison, and Boolean Operators" }, { "id": "ai-example-5", "kind": "correct", - "title": "a = 'This is a string'", - "code": "a = 'This is a string' \nb = \"This is another string\"\nprint(a)\nprint(b)\nprint(a,b)", + "title": "arithmetic_operators", + "code": "print(5//2, 5%2)", "why": "", - "output": "", + "output": "2 1", "status": "curated", - "subtopic_id": "w1-sequences-and-access-core", - "subtopic_title": "Indexing, Slicing, and range()" + "subtopic_id": "w1-operators-and-truth-core", + "subtopic_title": "Arithmetic, Comparison, and Boolean Operators" }, { "id": "ai-example-6", "kind": "correct", - "title": "a = 'This is a string'; b = 6; c = 0.0", - "code": "#\na = 'This is a string'; b = 6; c = 0.0 \nprint(f\"We know {a =}, {b= }, and {c = }\")", + "title": "arithmetic_operators", + "code": "print(4 + 3)\nprint(4 - 3)\nprint(4 * 3)\nprint(4 / 3)\nprint(4 / 2)\nprint(4 ** 3)", "why": "", - "output": "", + "output": "7\n1\n12\n1.3333333333333333\n2.0\n64", "status": "curated", - "subtopic_id": "w1-sequences-and-access-core", - "subtopic_title": "Indexing, Slicing, and range()" + "subtopic_id": "w1-operators-and-truth-core", + "subtopic_title": "Arithmetic, Comparison, and Boolean Operators" }, { "id": "ai-example-7", "kind": "correct", - "title": "slicing", - "code": "l1 = ['a', 'b']\nl2 = l1\nl2[-1] = 'c'\nprint(l1 == l3)\nl3 = l1[::]\nl3[-1] = 'c'\nprint(l1 == l3)", + "title": "arithmetic_operators", + "code": "print(5 // 3, 5 % 3)\nprint(-5 // 3, -5 % 3)\nprint(5 // 2, 5 % 2)\nprint(-5 // 2, -5 % 2)", "why": "", - "output": "", + "output": "1 2\n-2 1\n2 1\n-3 1", "status": "curated", - "subtopic_id": "w1-sequences-and-access-core", - "subtopic_title": "Indexing, Slicing, and range()" + "subtopic_id": "w1-operators-and-truth-core", + "subtopic_title": "Arithmetic, Comparison, and Boolean Operators" + }, + { + "id": "ai-example-8", + "kind": "correct", + "title": "`==` versus `is`", + "code": "#\nimport random # The random module that can be used to generate pseudo-random numbers is part of the standard Python installation\n # but the name has still to be importent\na = random.randint(3, 9) # This generates an integer between 3 and 9 (both included), it is given the name 'a'\nb = random.randint(3, 9) # # This generates an integer between 3 and 9 (both included), it is given the name 'b'\nprint (a, b)\nprint(a==(a/b)*b + a%b) # == compares what is left of it to what is right of it and evaluates to True if both sides evaluate to the same value", + "why": "`==` compares value equality; `is` compares whether two names refer to the same object.", + "output": "8 4\nTrue", + "status": "curated", + "subtopic_id": "w1-operators-and-truth-core", + "subtopic_title": "Arithmetic, Comparison, and Boolean Operators" } ], "recommended_ids": [ - "exam-extra_practice-6-w1-sequences-and-access", - "ks-685cd3d828", - "ks-be78ccac04", - "cs-60dd1a8d2c", - "cs-0af6442b99", - "cs-85d755c5e8", - "cs-8a4ee4419d" + "ks-03c874b8bb", + "ks-c0135e2a4a", + "ks-c815ffe1d5", + "cs-7eb8617d28", + "cs-3cb4b8e8f9", + "cs-266616a010", + "cs-4f8a5f420b" + ], + "homework_snippets": [ + { + "id": "hw-355b9824ed", + "week": 1, + "cell_index": 2, + "cell_type": "code", + "topic": "arithmetic_operators", + "source": "# source: materials/homework/week 1/Exercise 1.py\nprint(max(30 - x, 0))", + "outputs": [], + "source_origin": "materials/homework/week 1/Exercise 1.py" + }, + { + "id": "hw-2f73c03cca", + "week": 1, + "cell_index": 3, + "cell_type": "code", + "topic": "arithmetic_operators", + "source": "# source: materials/homework/week 1/Exercise_1.2.py\nprint(round(100 * (1 + x / 100)**4, 2))", + "outputs": [], + "source_origin": "materials/homework/week 1/Exercise_1.2.py" + }, + { + "id": "hw-dd152b8e7c", + "week": 1, + "cell_index": 4, + "cell_type": "code", + "topic": "arithmetic_operators", + "source": "# source: materials/homework/week 1/Exercise_1.3.py\nprint((64 // package_size) * package_price + (64 % package_size) * individual_price)", + "outputs": [], + "source_origin": "materials/homework/week 1/Exercise_1.3.py" + }, + { + "id": "hw-9b03246fee", + "week": 1, + "cell_index": 6, + "cell_type": "code", + "topic": "boolean_operators", + "source": "# source: materials/homework/week 1/Exercise_1.5.py\nprint('mnop' * (1 - x))", + "outputs": [], + "source_origin": "materials/homework/week 1/Exercise_1.5.py" + } + ], + "homework_recommended_ids": [ + "hw-355b9824ed", + "hw-2f73c03cca" ] } }, { - "id": "w1-functions-and-imports", - "topic": "Functions and Imports", - "canonical_topic": "w1-functions-and-imports", - "weeks": [ - 1 - ], - "week_id": "week-1", - "topic_meta": { - "week": 1, - "week_id": "week-1", - "week_title": "Week 1", - "topic_id": "w1-functions-and-imports", - "topic_title": "Functions and Imports", - "topic_order": 5 - }, - "subtopics": [ - { - "id": "w1-functions-and-imports-core", - "title": "Built-ins Intro, Functions, and Modules", - "order": 1, - "summary": "`import x` keeps the module name, `from x import y` brings `y` into scope, and `as` renames. Call functions with `()`, and keep `print` separate from returned values.", - "item_ids": { - "lecture_snippet_ids": [ - "ks-f43422a4cf", - "ks-b6a39f66a2" - ], - "exam_question_ids": [ - "exam-midterm_2023-12-w1-functions-and-imports", - "exam-midterm_2024-15-w1-functions-and-imports", - "exam-midterm_2024-16-w1-functions-and-imports", - "exam-Resit 22/23-5-w1-functions-and-imports" - ], - "notebook_snippet_ids": [ - "cs-beb6591b24", - "cs-6d0d650063", - "cs-4155022ebf", - "cs-23b2cfd4d6", - "cs-5b89a10dcd", - "cs-c25503e5db", - "cs-8a006d887d", - "cs-214144c1f0" - ], - "example_ids": [ - "ai-example-1", - "ai-example-2", - "ai-example-3", - "ai-example-4", - "ai-example-5", - "ai-example-6", - "ai-example-8" - ], - "key_point_ids": [ - "kp-1", - "kp-2" - ] - } - } - ], + "canonical_topic": "w1-sequences-and-access", "exam_stats": { - "total_hits": 4, + "total_hits": 1, "by_exam": { - "midterm_2024": 2, - "Resit 22/23": 1, - "midterm_2023": 1 + "extra_practice": 1 }, - "coverage_count": 3 + "coverage_count": 1 }, + "id": "w1-sequences-and-access", "related_topics": [ - "Built-ins Intro, Functions, and Modules" - ], - "trap_patterns": [ - { - "pattern": "Implicit return None", - "trap": "Function without return statement, or where return is not reached, returns None. print(func()) will print None.", - "weeks": [ - 3 - ], - "appears_in_exams": [ - "trial_midterm", - "extra_practice" - ] - } + "Indexing, Slicing, and range()" ], "sections": { "lecture_snippets": [ { - "id": "ks-f43422a4cf", + "id": "ks-685cd3d828", "week": 1, "source": "materials/lectures/Lecture Week 1.md", "source_type": "lecture", - "topic": "Functions and Imports", - "subtopic_id": "w1-functions-and-imports-core", - "subtopic_title": "Built-ins Intro, Functions, and Modules", - "title": "Importing packages", - "explanation": "Multiple import styles. 'import X' makes X available. 'import X as Y' renames. 'from X import Z' brings Z directly into namespace. 'from X import Z as W' renames. Once you use 'as', the original name is no longer accessible.", + "topic": "Sequences and Access", + "subtopic_id": "w1-sequences-and-access-core", + "subtopic_title": "Indexing, Slicing, and range()", + "title": "Indexing", + "explanation": "Forward: 0, 1, 2, ... len-1. Backward: -1 (last), -2 (second to last), ..., -len (first). l1[0] == l1[-len(l1)]", + "code_examples": [] + }, + { + "id": "ks-be78ccac04", + "week": 1, + "source": "materials/lectures/Lecture Week 1.md", + "source_type": "lecture", + "topic": "Sequences and Access", + "subtopic_id": "w1-sequences-and-access-core", + "subtopic_title": "Indexing, Slicing, and range()", + "title": "range()", + "explanation": "range(start, stop, step). start default=0, step default=1. Stop is NOT inclusive. Works like slicing but defaults differ slightly.", "code_examples": [ { - "description": "Import styles", - "code": "import numpy\nnumpy.random.randint(1, 10) # works\n\nimport numpy as np\nnp.random.randint(1, 10) # works\nnumpy.random.randint(1, 10) # ERROR\n\nfrom numpy.random import randint\nrandint(1, 10) # works\n\nfrom numpy.random import randint as rnd\nrnd(1, 10) # works\nrandint(1, 10) # ERROR" + "description": "range examples", + "code": "print(list(range(6))) # [0, 1, 2, 3, 4, 5]\nprint(list(range(3,6))) # [3, 4, 5]\nprint(list(range(3,6,2))) # [3, 5]" } ] - }, - { - "id": "ks-b6a39f66a2", - "week": 1, - "source": "materials/notebooks/Notebook Week 1.ipynb", - "source_type": "notebook", - "topic": "Functions and Imports", - "subtopic_id": "w1-functions-and-imports-core", - "subtopic_title": "Built-ins Intro, Functions, and Modules", - "title": "intro", - "explanation": "### Print is a function and tells Python to output the argument (that what is between the brackets after the function name) on your screen\n
    • A function is a grouping of code that can perform a certain task and can be re-used \n
    • Print is a built-in function, that is a function that is part of the standard implementation of Python. Built-in fuctions like any function, can be used by calling their name. Built-in functions are already copied to your computer and the names of some of them like print, don't need to be imported\n
    • User functions are functions defined by you or other people that are not part of the standard Python implementation. (You will learn how to write your own…", - "code_examples": [] } ], "exam_questions": [ { - "id": "exam-midterm_2023-12-w1-functions-and-imports", - "exam_label": "midterm_2023", - "exam_source": "materials/exams/2023.pdf", - "year": "2022-2023", - "number": 12, - "week": 1, - "topic": "function", - "subtopic_id": "w1-functions-and-imports-core", - "subtopic_title": "Built-ins Intro, Functions, and Modules", - "question": "You want to write a program to calculate your income tax for 2023.", - "code_context": "Suppose your country imposes the following tax brackets:\nBracket Tax Taxable income\nrate Over Not over\n1 10% $0 $11,000\n2 12% $11,000 $45,000\n3 22% $45,000 $95,000\n4 32% $95,000\nIf your gross income is $50,000, you will pay 10% tax on the first $11,000, 12% tax on the next $34,000 and 22% tax on the last $5,000.\nWhich of the following function will return the output containing your net_income and your total_tax given your gross_income?\nFor example:\nIf we call the function as:\nincome_tax_calculator(50000)\nit should return:\n{'total_tax': 6280.0, 'net_income': 43720.0}\nA def income_tax_calculator(gross_income):\nresults = {}\nrate_1 = 0.10\nrate_2 = 0.12\nrate_3 = 0.22\nrate_4 = 0.32\nbracket_1 = 11000\nbracket_2 = 45000 - 11000\nbracket_3 = 95000 - 45000\nif gross_income > 95000:\ntotal_tax = ((gross_income - 95000) * rate_4) + (bracket_3 * rate_3) + (bracket_2 * rate_2)\n+ (bracket_1 * rate_1)\nelif 95000 >= gross_income > 45000:\ntotal_tax = ((gross_income - 45000) * rate_3) + (bracket_2 * rate_2) + (bracket_1 * rate_1)\nelif 45000 >= gross_income > 11000:\ntotal_tax = ((gross_income - 11000) * rate_2) + (bracket_1 * rate_1)\nelse:\ntotal_tax = gross_income * rate_1\nnet_income = gross_income - total_tax\nresults['total_tax'] = round(total_tax, 2)\nresults['net_income'] = round(net_income, 2)\nreturn results\nB def income_tax_calculator(gross_income):\n​ results = {}\nrate_1 = 0.10\nrate_2 = 0.12\nrate_3 = 0.22\nrate_4 = 0.32\nbracket_1 = 11000\nbracket_2 = 45000 - 11001\nbracket_3 = 95000 - 45001\ntotal_tax = (gross_income - 95001) * rate_4 + (bracket_3 * rate_3) + (bracket_2 * rate_2) +\n(bracket_1 * rate_1)\nnet_income = lambda gross_income, total_tax: gross_income - total_tax\nresults['total_tax'] = round(total_tax, 2)\nresults['net_income'] = round(net_income, 2)\nreturn results\nC def income_tax_calculator(gross_income):\n​ results = {}\nrate_1 = 0.10\nrate_2 = 0.12\nrate_3 = 0.22\nrate_4 = 0.32\nif gross_income <= 11000:\ntotal_tax = gross_income * rate_1\nif 45000 > gross_income > 11000:\ntotal_tax += (45000 - gross_income) * rate_2\nif 95000 > gross_income > 45000:\ntotal_tax += (95000 - gross_income) * rate_3\nelse:\ntotal_tax += (gross_income - 95000) * rate_4\nnet_income = gross_income - total_tax\nresults['total_tax'] = total_tax\nresults['net_income'] = net_income\nreturn(total_tax, net_income)\nD All of three functions will work as intended.", - "options": {}, - "correct": "", - "explanation": "" - }, - { - "id": "exam-midterm_2024-15-w1-functions-and-imports", - "exam_label": "midterm_2024", - "exam_source": "materials/exams/2024.pdf", - "year": "2023-2024", - "number": 15, - "week": 1, - "topic": "function", - "subtopic_id": "w1-functions-and-imports-core", - "subtopic_title": "Built-ins Intro, Functions, and Modules", - "question": "Consider the following code snippet:\ndef main(lst, condition=lambda x: x):\ny = []\nfor x in lst:\nif condition(x):\ny.append(x)\nreturn y\nWhat will this function return, when called in the following way:\nmain([1, 2, 3, 4, 5, 6, 7, 8, 9, 10], lambda x: x % 2 != 0)\nA [1, 3, 5, 7, 9]\nB [2, 4, 6, 8, 10]\nC [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]\nD None", - "code_context": "Consider the following code snippet:\ndef main(lst, condition=lambda x: x):\ny = []\nfor x in lst:\nif condition(x):\ny.append(x)\nreturn y\nWhat will this function return, when called in the following way:\nmain([1, 2, 3, 4, 5, 6, 7, 8, 9, 10], lambda x: x % 2 != 0)\nA [1, 3, 5, 7, 9]\nB [2, 4, 6, 8, 10]\nC [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]\nD None", - "options": {}, - "correct": "", - "explanation": "" - }, - { - "id": "exam-midterm_2024-16-w1-functions-and-imports", - "exam_label": "midterm_2024", - "exam_source": "materials/exams/2024.pdf", - "year": "2023-2024", - "number": 16, + "id": "exam-extra_practice-6-w1-sequences-and-access", + "exam_label": "extra_practice", + "exam_source": "materials/exams/Midterm Extra Practice.txt", + "year": "unknown", + "number": 6, "week": 1, - "topic": "function", - "subtopic_id": "w1-functions-and-imports-core", - "subtopic_title": "Built-ins Intro, Functions, and Modules", - "question": "You need to write a function called weather_alert that accepts a string argument, which is a color code of the weather alert system.", - "code_context": "Your function should return one of the following lines to inform the citizens of what to do depending on the color:\nIf the color is red, return: \"Take action to protect against severe condition.\"\nIf the color is orange, return: \"Be prepared for damages.\"\nIf the color is yellow, return: \"Be alert for potential hazard.\"\nFor any other colors, return: \"No warning.\"\nWhich of the following program will do want you need?\nA def weather_alert(color):\nif color == \"red\":\nreturn \"Take action to protect against severe condition.\"\nelif color == \"orange\":\nreturn \"Be prepared for damages.\"\nelif color == \"yellow\":\nreturn \"Be alert for potential hazard.\"\nreturn \"No warning.\"\nB def weather_alert(color):\nif color == \"red\":\nprint(\"Take action to protect against severe condition.\")\nelif color == \"orange\":\nprint(\"Be prepared for damages.\")\nelif color == \"yellow\":\nprint(\"Be alert for potential hazard.\")\nelse:\nprint(\"No warning.\")\nC def weather_alert(color):\nif color == \"red\":\nreturn \"Take action to protect against severe condition.\"\nelif color == \"orange\":\nreturn \"Be prepared for damages.\"\nelif color == \"yellow\":\nreturn \"Be alert for potential hazard.\"\nelif color == \"green\":\nreturn \"No warning.\"\nD All of the programs should work as intended.", - "options": {}, - "correct": "", - "explanation": "" + "topic": "slicing / negative step", + "subtopic_id": "w1-sequences-and-access-core", + "subtopic_title": "Indexing, Slicing, and range()", + "question": "numbers = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]\n\nWhich of the following lines of code will NOT create a list with the name subset, and the value [10, 8, 6, 4, 2]?", + "code_context": "", + "options": { + "a": "subset = numbers[-1::-2]", + "b": "subset = numbers[::-2]", + "c": "subset = numbers[::-1][::2]", + "d": "subset = numbers[::2][::-1]" + }, + "correct": "d", + "explanation": "a: starts at -1 (10), step -2: [10,8,6,4,2]. Correct. b: [::-2] starts at last (10), step -2: [10,8,6,4,2]. Correct. c: [::-1] reverses to [10,9,8,7,6,5,4,3,2,1], then [::2] takes every 2nd: [10,8,6,4,2]. Correct. d: [::2] gives [1,3,5,7,9], then [::-1] reverses: [9,7,5,3,1]. This does NOT give [10,8,6,4,2]. Correct answer (the one that does NOT work): d." }, { - "id": "exam-Resit 22/23-5-w1-functions-and-imports", - "exam_label": "Resit 22/23", - "exam_source": "materials/post_midterm/practice_exams_previous_years/resit-solutions-for-introduction-to-python-35761538.pdf", - "year": "2022-2023", - "number": 5, + "id": "exam-intro_python_sample_final_24_25-18-w2-conditions", + "exam_label": "intro_python_sample_final_24_25", + "exam_source": "materials/post_midterm/Sample Final plus answers.pdf", + "year": "2024", + "number": 18, "week": 1, - "topic": "3_Function_Built-in_2", - "subtopic_id": "w1-functions-and-imports-core", - "subtopic_title": "Built-ins Intro, Functions, and Modules", - "question": "Suppose you have a list called x. Which of the following code segments will print the following list?\n[5, 4, 3, 2, 1]", - "code_context": "x = [1, 1, 2, 2, 3, 3, 4, 4, 5, 5]", + "topic": "Slicing", + "subtopic_id": "w1-sequences-and-access-core", + "subtopic_title": "Indexing, Slicing, and range()", + "question": "How do you break a list into a list of lists, where each sublist contains 3 elements?", + "code_context": "x = ['a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i']", "options": { - "a": "y = list(set(x))\nprint(sorted(y, reverse = True))", - "b": "print(x[::-2])", - "c": "Both lines of code will print that output.", - "d": "Neither line of code will print that output." + "A": "y = [x[i:(i + 3)] for i in range(0, 7, 3)]", + "B": "y = [x[i[0]::3] for i in enumerate(x)]", + "C": "Both of the above work", + "D": "Neither of above works" }, - "correct": "c", - "explanation": "Option A extracts unique elements with `set(x)`, resulting in `{1, 2, 3, 4, 5}`, then sorts them in reverse order, giving `[5, 4, 3, 2, 1]`. Option B uses list slicing `x[::-2]` which steps backwards through `x` by 2, retrieving indices -1, -3, -5, -7, and -9, which correspond to 5, 4, 3, 2, 1. Thus, both A and B are correct." + "correct": "A", + "explanation": "Option A uses range(0, 7, 3) which generates 0, 3, 6. The slices x[0:3], x[3:6], and x[6:9] correctly partition the list." } ], "notebook_snippets": [ { - "id": "cs-beb6591b24", + "id": "cs-60dd1a8d2c", "week": 1, "cell_index": null, "cell_type": "code", "source_type": "notebook", - "topic": "Functions and Imports", - "subtopic_id": "w1-functions-and-imports-core", - "subtopic_title": "Built-ins Intro, Functions, and Modules", - "title": "imports", - "source": "clear_names()\n\nimport extension as ex\ntry:\n print(ex.YEAR)\nexcept Exception as e:\n print(e)\n\ntry:\n print(extension.YEAR)\nexcept Exception as e:\n print(e)", - "outputs": [ - "2025\nname 'extension' is not defined" - ] + "topic": "Sequences and Access", + "subtopic_id": "w1-sequences-and-access-core", + "subtopic_title": "Indexing, Slicing, and range()", + "title": "print(\"This is a string\")", + "source": "print(\"This is a string\")\nprint('This is another string')", + "outputs": [] }, { - "id": "cs-6d0d650063", + "id": "cs-0af6442b99", "week": 1, "cell_index": null, "cell_type": "code", "source_type": "notebook", - "topic": "Functions and Imports", - "subtopic_id": "w1-functions-and-imports-core", - "subtopic_title": "Built-ins Intro, Functions, and Modules", - "title": "imports", - "source": "clear_names()\n\nimport extension\nimport extension as ex\ntry:\n print(ex.YEAR)\nexcept Exception as e:\n print(e)\n\ntry:\n print(extension.YEAR)\nexcept Exception as e:\n print(e)", - "outputs": [ - "2025\n2025" - ] + "topic": "Sequences and Access", + "subtopic_id": "w1-sequences-and-access-core", + "subtopic_title": "Indexing, Slicing, and range()", + "title": "strings_quotes", + "source": "print('This gives an error\")\nprint(\"This gives an error')", + "outputs": [] }, { - "id": "cs-4155022ebf", + "id": "cs-85d755c5e8", "week": 1, "cell_index": null, "cell_type": "code", "source_type": "notebook", - "topic": "Functions and Imports", - "subtopic_id": "w1-functions-and-imports-core", - "subtopic_title": "Built-ins Intro, Functions, and Modules", - "title": "imports", - "source": "clear_names()\n\nfrom extension import create_absolute_year\ntry:\n print(create_absolute_year(1))\nexcept Exception as e:\n print(e)\n\ntry:\n print(YEAR)\nexcept Exception as e:\n print(e)", - "outputs": [ - "2026\nname 'YEAR' is not defined" - ] + "topic": "Sequences and Access", + "subtopic_id": "w1-sequences-and-access-core", + "subtopic_title": "Indexing, Slicing, and range()", + "title": "strings_quotes", + "source": "print(\"This gives no ' error\")\nprint('This gives no \" error')", + "outputs": [] }, { - "id": "cs-23b2cfd4d6", + "id": "cs-8a4ee4419d", "week": 1, "cell_index": null, "cell_type": "code", "source_type": "notebook", - "topic": "Functions and Imports", - "subtopic_id": "w1-functions-and-imports-core", - "subtopic_title": "Built-ins Intro, Functions, and Modules", - "title": "imports", - "source": "clear_names()\n\nfrom extension import create_absolute_year as cay\ntry:\n print(create_absolute_year(1))\nexcept Exception as e:\n print(e)\n\ntry:\n print(cay(1))\nexcept Exception as e:\n print(e)", - "outputs": [ - "name 'create_absolute_year' is not defined\n2026" - ] + "topic": "Sequences and Access", + "subtopic_id": "w1-sequences-and-access-core", + "subtopic_title": "Indexing, Slicing, and range()", + "title": "a = 'This is a string'", + "source": "a = 'This is a string' \nb = \"This is another string\"\nprint(a)\nprint(b)\nprint(a,b)", + "outputs": [] }, { - "id": "cs-5b89a10dcd", + "id": "cs-7ac6156d67", "week": 1, "cell_index": null, "cell_type": "code", "source_type": "notebook", - "topic": "Functions and Imports", - "subtopic_id": "w1-functions-and-imports-core", - "subtopic_title": "Built-ins Intro, Functions, and Modules", - "title": "imports", - "source": "clear_names()\ntry:\n print(YEAR)\nexcept Exception as e:\n print(Exception)\n\ntry:\n print(extension.YEAR)\nexcept Exception as e:\n print(e)\n\nimport extension\ntry:\n print(YEAR)\nexcept Exception as e:\n print(e)\n\ntry:\n print(extension.YEAR)\nexcept Exception as e:\n print(e)", - "outputs": [ - "\nname 'extension' is not defined\nname 'YEAR' is not defined\n2025" - ] + "topic": "Sequences and Access", + "subtopic_id": "w1-sequences-and-access-core", + "subtopic_title": "Indexing, Slicing, and range()", + "title": "a = 'This is a string'; b = 6; c = 0.0", + "source": "#\na = 'This is a string'; b = 6; c = 0.0 \nprint(f\"We know {a =}, {b= }, and {c = }\")", + "outputs": [] }, { - "id": "cs-c25503e5db", + "id": "cs-15d46dcc2c", "week": 1, "cell_index": null, "cell_type": "code", "source_type": "notebook", - "topic": "Functions and Imports", - "subtopic_id": "w1-functions-and-imports-core", - "subtopic_title": "Built-ins Intro, Functions, and Modules", - "title": "imports", - "source": "%%writefile extension.py\n# In this cell we create a python file and write that to the hard disk (either of your computer or to the cloud depending where you run your code.\n# We will import this file to show how to import the names of objects \n# into your Python program\nYEAR = 2025\ndef create_absolute_year(x):\n return YEAR + x", - "outputs": [ - "Overwriting extension.py" - ] + "topic": "Sequences and Access", + "subtopic_id": "w1-sequences-and-access-core", + "subtopic_title": "Indexing, Slicing, and range()", + "title": "slicing", + "source": "l1 = ['a', 'b']\nl2 = l1\nl2[-1] = 'c'\nprint(l1 == l3)\nl3 = l1[::]\nl3[-1] = 'c'\nprint(l1 == l3)", + "outputs": [] }, { - "id": "cs-8a006d887d", + "id": "cs-ab9dc084b6", "week": 1, "cell_index": null, "cell_type": "code", "source_type": "notebook", - "topic": "Functions and Imports", - "subtopic_id": "w1-functions-and-imports-core", - "subtopic_title": "Built-ins Intro, Functions, and Modules", - "title": "import dis", - "source": "#\nimport dis\ndef func():\n print('Hello World')\ndis.dis(func)", + "topic": "Sequences and Access", + "subtopic_id": "w1-sequences-and-access-core", + "subtopic_title": "Indexing, Slicing, and range()", + "title": "a = 'This is a string'", + "source": "a = 'This is a string' \nb = \"This is another string\"\nprint(a + b)\nprint(\"First string: '\" + a + \"', Second string: '\" + b + \"'.\")", "outputs": [] }, { - "id": "cs-214144c1f0", + "id": "cs-59038bcffa", "week": 1, "cell_index": null, "cell_type": "code", "source_type": "notebook", - "topic": "Functions and Imports", - "subtopic_id": "w1-functions-and-imports-core", - "subtopic_title": "Built-ins Intro, Functions, and Modules", - "title": "from decimal import Decimal", - "source": "#\nfrom decimal import Decimal\nprint(Decimal('1.1') + Decimal('2.2'))", + "topic": "Sequences and Access", + "subtopic_id": "w1-sequences-and-access-core", + "subtopic_title": "Indexing, Slicing, and range()", + "title": "strings_fstrings", + "source": "a = 'This is a string' \nb = \"This is another string\"\nprint(f\"First string: '{a}', Second string: '{b}'.\")\nprint(\"First string: '{a}', Second string: '{b}'.\")", "outputs": [] + }, + { + "id": "cs-curated-hw-seq-nth-occurrence", + "week": 1, + "cell_index": null, + "cell_type": "code", + "source_type": "notebook", + "topic": "Sequences and Access", + "subtopic_id": "w1-sequences-and-access-core", + "subtopic_title": "Indexing, Slicing, and range()", + "title": "Find the nth occurrence by advancing .index()", + "source": "x = ['A', 'B', 'A', 'C', 'B', 'A', 'B']\nn = 2\ni = -1\nfor _ in range(n):\n i = x.index('B', i + 1)\nprint(i)", + "outputs": [ + "4" + ] + }, + { + "id": "cs-curated-hw-seq-slice-between-sentinels", + "week": 1, + "cell_index": null, + "cell_type": "code", + "source_type": "notebook", + "topic": "Sequences and Access", + "subtopic_id": "w1-sequences-and-access-core", + "subtopic_title": "Indexing, Slicing, and range()", + "title": "Slice between two sentinel values without hard-coding indices", + "source": "x = [21, 15, 29, 20, 15, 21, 38, 26]\nleft = x.index(15) + 1\nright = left + x[left:].index(15)\nprint(x[left:right])", + "outputs": [ + "[29, 20]" + ] } ], "ai_summary": { "status": "curated", - "content": "`import x` keeps the module name, `from x import y` brings `y` into scope, and `as` renames. Call functions with `()`, and keep `print` separate from returned values.", + "content": "Use `seq[start:stop:step]` with stop excluded. Negative indices count from the end, and `range(start, stop, step)` follows the same stop-excluded rule.", "generator": "lecture-first-build", "model": null }, "ai_common_questions": { "status": "curated", "bullets": [ - "You want to write a program to calculate your income tax for 2023.", - "Consider the following code snippet:\ndef main(lst, condition=lambda x: x):\ny = []\nfor x in lst:\nif condition(x):\ny.append(x)\nreturn y\nWhat will this function return, when called in the following way:\nmain([1, 2, 3, 4, 5, 6, 7, 8, 9, 10], lambda x: x % 2 != 0)…", - "You need to write a function called weather_alert that accepts a string argument, which is a color code of the weather alert system.", - "Suppose you have a list called x. Which of the following code segments will print the following list?\n[5, 4, 3, 2, 1]", - "Function without return statement, or where return is not reached, returns None. print(func()) will print None." + "s.upper() returns a new string; s is unchanged. Must do s = s.upper()", + "range(1,10,3)→[1,4,7] not including 10; l[2:7] goes up to but not including index 7", + "l[::-2] starts from last element going backwards with step 2. l[::2][::-1] first takes every other starting from 0, then reverses — different result" ], "items": [ { - "id": "manual-import-names", - "summary": "How do different import forms change the names you can use locally?", - "detail": "`import math` gives `math.sqrt`, `import math as m` gives `m.sqrt`, and `from math import sqrt` gives `sqrt(...)` directly.", - "extra": "", - "code": "import math\nimport math as m\nfrom math import sqrt", - "table": null + "id": "aiq-1", + "summary": "Slicing / mutability", + "detail": "Track which names point to the same object and which slice creates a copy before the mutation happens.", + "extra": "Slicing / mutability", + "subtopic_id": "w1-sequences-and-access-core", + "subtopic_title": "Indexing, Slicing, and range()" }, { - "id": "manual-print-vs-return", - "summary": "What is the difference between printing a value and returning a value from a function?", - "detail": "`print(x)` shows a value on screen. `return x` sends a value back to the caller so it can be stored, reused, or printed later.", + "id": "aiq-2", + "summary": "Slicing negative step", + "detail": "Read the slice as `start:stop:step`; with a negative step Python walks right-to-left and still excludes the stop position.", + "extra": "Slicing negative step", + "subtopic_id": "w1-sequences-and-access-core", + "subtopic_title": "Indexing, Slicing, and range()" + }, + { + "id": "aiq-3", + "summary": "numbers = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]", + "detail": "a: starts at -1 (10), step -2: [10,8,6,4,2]. Correct. b: [::-2] starts at last (10), step -2: [10,8,6,4,2]. Correct. c: [::-1] reverses to [10,9,8,7,6,5,4,3,2,1], then [::2] takes every 2nd: [10,8,6,4,2]. Correct. d: [::2] gives [1,3,5,7,9], then [::-1] reverses: [9,7,5,3,1]. This does NOT give [10,8,6,4,2].", + "extra": "Exam • extra_practice • Q6", + "subtopic_id": "w1-sequences-and-access-core", + "subtopic_title": "Indexing, Slicing, and range()" + }, + { + "id": "aiq-5", + "summary": "str.upper() / string methods don't modify in place", + "detail": "s.upper() returns a new string; s is unchanged. Must do s = s.upper()", "extra": "", - "code": "def f(x):\n return x + 1\n\nprint(f(3))", - "table": null + "subtopic_id": "", + "subtopic_title": "" }, { - "id": "manual-implicit-none", - "summary": "What does a function return if it reaches the end without `return`?", - "detail": "Python returns `None` if no `return` statement is executed.", + "id": "aiq-6", + "summary": "range() and slicing both exclusive at stop", + "detail": "range(1,10,3)→[1,4,7] not including 10; l[2:7] goes up to but not including index 7", "extra": "", - "code": "def f():\n print('hi')\n\nprint(f())", - "table": null + "subtopic_id": "", + "subtopic_title": "" } ], "generator": "lecture-first-build", @@ -2916,49 +2414,43 @@ "key_points_to_remember": [ { "id": "kp-1", - "text": "`import x` keeps the module name, `import x as y` renames it, and `from x import z` brings `z` into scope directly.", + "text": "Negative indices count from the end: `seq[-1]` is last and `seq[-len(seq)]` is first.", "status": "curated", "generator": "lecture-first-build", "model": null, - "subtopic_id": "w1-functions-and-imports-core", - "subtopic_title": "Built-ins Intro, Functions, and Modules", + "subtopic_id": "w1-sequences-and-access-core", + "subtopic_title": "Indexing, Slicing, and range()", "details": [ { "id": "kp-1-d1", - "kind": "example", - "title": "Import styles", - "code": "import numpy\nnumpy.random.randint(1, 10) # works\n\nimport numpy as np\nnp.random.randint(1, 10) # works\nnumpy.random.randint(1, 10) # ERROR\n\nfrom numpy.random import randint\nrandint(1, 10) # works\n\nfrom numpy.random import randint as rnd\nrnd(1, 10) # works\nrandint(1, 10) # ERROR" - }, - { - "id": "kp-1-d2", "kind": "table", "title": "Dense reference table", "table": { "headers": [ - "Call", - "Use", - "Typical result" + "Pattern", + "Meaning", + "Example" ], "rows": [ [ - "int('123')", - "string to integer", - "123" + "seq[i]", + "single element", + "x[-1]" ], [ - "float('123')", - "string to float", - "123.0" + "seq[a:b]", + "start inclusive, stop exclusive", + "x[1:4]" ], [ - "str(123.0)", - "number to string", - "'123.0'" + "seq[::-1]", + "reverse copy", + "x[::-1]" ], [ - "round(x, 2)", - "round for display/checking", - "2 decimals" + "seq[::2]", + "step through every other item", + "x[::2]" ] ] } @@ -2967,12 +2459,29 @@ }, { "id": "kp-2", - "text": "Use `print(...)` to display a value. A function groups reusable code and may also return a value to its caller.", + "text": "`range(start, stop, step)` excludes `stop`; defaults are `start=0` and `step=1`, just like slicing excludes the stop index.", "status": "curated", "generator": "lecture-first-build", "model": null, - "subtopic_id": "w1-functions-and-imports-core", - "subtopic_title": "Built-ins Intro, Functions, and Modules", + "subtopic_id": "w1-sequences-and-access-core", + "subtopic_title": "Indexing, Slicing, and range()", + "details": [ + { + "id": "kp-2-d1", + "kind": "example", + "title": "range examples", + "code": "print(list(range(6))) # [0, 1, 2, 3, 4, 5]\nprint(list(range(3,6))) # [3, 4, 5]\nprint(list(range(3,6,2))) # [3, 5]" + } + ] + }, + { + "id": "kp-3", + "text": "Pattern to remember: subset = numbers[::2][::-1]", + "status": "curated", + "generator": "lecture-first-build", + "model": null, + "subtopic_id": "w1-sequences-and-access-core", + "subtopic_title": "Indexing, Slicing, and range()", "details": [] } ], @@ -2980,157 +2489,145 @@ { "id": "ai-example-1", "kind": "correct", - "title": "Import module under its original name", - "code": "import numpy\nnumpy.random.randint(1, 10) # works\n\nimport numpy as np\nnp.random.randint(1, 10) # works\nnumpy.random.randint(1, 10) # ERROR\n\nfrom numpy.random import randint\nrandint(1, 10) # works\n\nfrom numpy.random import randint as rnd\nrnd(1, 10) # works\nrandint(1, 10) # ERROR", - "why": "`import x` keeps the module name, `import x as y` renames it, and `from x import z` brings `z` into scope directly.", + "title": "range() output patterns", + "code": "print(list(range(6))) # [0, 1, 2, 3, 4, 5]\nprint(list(range(3,6))) # [3, 4, 5]\nprint(list(range(3,6,2))) # [3, 5]", + "why": "`range(start, stop, step)` excludes `stop`; defaults are `start=0` and `step=1`, just like slicing excludes the stop index.", "output": "", "status": "curated", - "subtopic_id": "w1-functions-and-imports-core", - "subtopic_title": "Built-ins Intro, Functions, and Modules" + "subtopic_id": "w1-sequences-and-access-core", + "subtopic_title": "Indexing, Slicing, and range()" }, { "id": "ai-example-2", "kind": "correct", - "title": "Direct import plus alias binds both names", - "code": "clear_names()\n\nimport extension as ex\ntry:\n print(ex.YEAR)\nexcept Exception as e:\n print(e)\n\ntry:\n print(extension.YEAR)\nexcept Exception as e:\n print(e)", - "why": "Keep track of which name is actually available after `import`, `from ... import ...`, or `as`.", - "output": "2025\nname 'extension' is not defined", + "title": "print(\"This is a string\")", + "code": "print(\"This is a string\")\nprint('This is another string')", + "why": "", + "output": "", "status": "curated", - "subtopic_id": "w1-functions-and-imports-core", - "subtopic_title": "Built-ins Intro, Functions, and Modules" + "subtopic_id": "w1-sequences-and-access-core", + "subtopic_title": "Indexing, Slicing, and range()" }, { - "id": "ai-example-3", + "id": "ai-example-4", "kind": "correct", - "title": "from-import binds only the imported name", - "code": "clear_names()\n\nimport extension\nimport extension as ex\ntry:\n print(ex.YEAR)\nexcept Exception as e:\n print(e)\n\ntry:\n print(extension.YEAR)\nexcept Exception as e:\n print(e)", - "why": "Keep track of which name is actually available after `import`, `from ... import ...`, or `as`.", - "output": "2025\n2025", + "title": "String quotes and escaping", + "code": "print(\"This gives no ' error\")\nprint('This gives no \" error')", + "why": "", + "output": "", "status": "curated", - "subtopic_id": "w1-functions-and-imports-core", - "subtopic_title": "Built-ins Intro, Functions, and Modules" + "subtopic_id": "w1-sequences-and-access-core", + "subtopic_title": "Indexing, Slicing, and range()" }, { - "id": "ai-example-4", + "id": "ai-example-5", "kind": "correct", - "title": "Aliased from-import uses the alias locally", - "code": "clear_names()\n\nfrom extension import create_absolute_year\ntry:\n print(create_absolute_year(1))\nexcept Exception as e:\n print(e)\n\ntry:\n print(YEAR)\nexcept Exception as e:\n print(e)", - "why": "Keep track of which name is actually available after `import`, `from ... import ...`, or `as`.", - "output": "2026\nname 'YEAR' is not defined", - "status": "curated", - "subtopic_id": "w1-functions-and-imports-core", - "subtopic_title": "Built-ins Intro, Functions, and Modules" - }, - { - "id": "ai-example-5", - "kind": "correct", - "title": "import module does not create bare globals", - "code": "clear_names()\n\nfrom extension import create_absolute_year as cay\ntry:\n print(create_absolute_year(1))\nexcept Exception as e:\n print(e)\n\ntry:\n print(cay(1))\nexcept Exception as e:\n print(e)", - "why": "Keep track of which name is actually available after `import`, `from ... import ...`, or `as`.", - "output": "name 'create_absolute_year' is not defined\n2026", + "title": "a = 'This is a string'", + "code": "a = 'This is a string' \nb = \"This is another string\"\nprint(a)\nprint(b)\nprint(a,b)", + "why": "", + "output": "", "status": "curated", - "subtopic_id": "w1-functions-and-imports-core", - "subtopic_title": "Built-ins Intro, Functions, and Modules" + "subtopic_id": "w1-sequences-and-access-core", + "subtopic_title": "Indexing, Slicing, and range()" }, { "id": "ai-example-6", "kind": "correct", - "title": "Import module under its original name", - "code": "clear_names()\ntry:\n print(YEAR)\nexcept Exception as e:\n print(Exception)\n\ntry:\n print(extension.YEAR)\nexcept Exception as e:\n print(e)\n\nimport extension\ntry:\n print(YEAR)\nexcept Exception as e:\n print(e)\n\ntry:\n print(extension.YEAR)\nexcept Exception as e:\n print(e)", - "why": "Keep track of which name is actually available after `import`, `from ... import ...`, or `as`.", - "output": "\nname 'extension' is not defined\nname 'YEAR' is not defined\n2025", + "title": "a = 'This is a string'; b = 6; c = 0.0", + "code": "#\na = 'This is a string'; b = 6; c = 0.0 \nprint(f\"We know {a =}, {b= }, and {c = }\")", + "why": "", + "output": "", "status": "curated", - "subtopic_id": "w1-functions-and-imports-core", - "subtopic_title": "Built-ins Intro, Functions, and Modules" + "subtopic_id": "w1-sequences-and-access-core", + "subtopic_title": "Indexing, Slicing, and range()" }, { - "id": "ai-example-8", - "kind": "incorrect", - "title": "Income tax branches and return shape", - "code": "Suppose your country imposes the following tax brackets:\nBracket Tax Taxable income\nrate Over Not over\n1 10% $0 $11,000\n2 12% $11,000 $45,000\n3 22% $45,000 $95,000\n4 32% $95,000\nIf your gross income is $50,000, you will pay 10% tax on the first $11,000, 12% tax on the next $34,000 and 22% tax on the last $5,000.\nWhich of the following function will return the output containing your net_income and your total_tax given your gross_income?\nFor example:\nIf we call the function as:\nincome_tax_calculator(50000)\nit should return:\n{'total_tax': 6280.0, 'net_income': 43720.0}\nA def income_tax_calculator(gross_income):\nresults = {}\nrate_1 = 0.10\nrate_2 = 0.12\nrate_3 = 0.22\nrate_4 = 0.32\nbracket_1 = 11000\nbracket_2 = 45000 - 11000\nbracket_3 = 95000 - 45000\nif gross_income > 95000:\ntotal_tax = ((gross_income - 95000) * rate_4) + (bracket_3 * rate_3) + (bracket_2 * rate_2)\n+ (bracket_1 * rate_1)\nelif 95000 >= gross_income > 45000:\ntotal_tax = ((gross_income - 45000) * rate_3) + (bracket_2 * rate_2) + (bracket_1 * rate_1)\nelif 45000 >= gross_income > 11000:\ntotal_tax = ((gross_income - 11000) * rate_2) + (bracket_1 * rate_1)\nelse:\ntotal_tax = gross_income * rate_1\nnet_income = gross_income - total_tax\nresults['total_tax'] = round(total_tax, 2)\nresults['net_income'] = round(net_income, 2)\nreturn results\nB def income_tax_calculator(gross_income):\n​ results = {}\nrate_1 = 0.10\nrate_2 = 0.12\nrate_3 = 0.22\nrate_4 = 0.32\nbracket_1 = 11000\nbracket_2 = 45000 - 11001\nbracket_3 = 95000 - 45001\ntotal_tax = (gross_income - 95001) * rate_4 + (bracket_3 * rate_3) + (bracket_2 * rate_2) +\n(bracket_1 * rate_1)\nnet_income = lambda gross_income, total_tax: gross_income - total_tax\nresults['total_tax'] = round(total_tax, 2)\nresults['net_income'] = round(net_income, 2)\nreturn results\nC def income_tax_calculator(gross_income):\n​ results = {}\nrate_1 = 0.10\nrate_2 = 0.12\nrate_3 = 0.22\nrate_4 = 0.32\nif gross_income <= 11000:\ntotal_tax = gross_income * rate_1\nif 45000 > gross_income > 11000:\ntotal_tax += (45000 - gross_income) * rate_2\nif 95000 > gross_income > 45000:\ntotal_tax += (95000 - gross_income) * rate_3\nelse:\ntotal_tax += (gross_income - 95000) * rate_4\nnet_income = gross_income - total_tax\nresults['total_tax'] = total_tax\nresults['net_income'] = net_income\nreturn(total_tax, net_income)\nD All of three functions will work as intended.", - "why": "Check branch boundaries, rounding, and whether the function returns `{'total_tax': ..., 'net_income': ...}`.", + "id": "ai-example-7", + "kind": "correct", + "title": "slicing", + "code": "l1 = ['a', 'b']\nl2 = l1\nl2[-1] = 'c'\nprint(l1 == l3)\nl3 = l1[::]\nl3[-1] = 'c'\nprint(l1 == l3)", + "why": "", "output": "", "status": "curated", - "subtopic_id": "w1-functions-and-imports-core", - "subtopic_title": "Built-ins Intro, Functions, and Modules" + "subtopic_id": "w1-sequences-and-access-core", + "subtopic_title": "Indexing, Slicing, and range()" } ], "recommended_ids": [ - "exam-midterm_2023-12-w1-functions-and-imports", - "exam-midterm_2024-15-w1-functions-and-imports", - "exam-midterm_2024-16-w1-functions-and-imports", - "exam-Resit 22/23-5-w1-functions-and-imports", - "ks-f43422a4cf", - "ks-b6a39f66a2", - "cs-beb6591b24", - "cs-6d0d650063" + "exam-intro_python_sample_final_24_25-18-w2-conditions", + "exam-extra_practice-6-w1-sequences-and-access", + "ks-685cd3d828", + "ks-be78ccac04", + "cs-60dd1a8d2c", + "cs-0af6442b99", + "cs-85d755c5e8", + "cs-8a4ee4419d" + ], + "homework_snippets": [ + { + "id": "hw-4d85ae1fd0", + "week": 1, + "cell_index": 1, + "cell_type": "code", + "topic": "indexing", + "source": "x = ['A','B','A','C','B','A','B']\nn = input('The index of which iteration of B would you like to find?')\ni = -1\ntry:\n for j in range(int(n)):\n i = x.index('B',i+1)\n print(i)\nexcept ValueError:\n print('There are fewer than ' + n + ' instances of B in the list.') #Either this\n print('There are only ' + str(j) + ' instances of B in the list.') #or this option is fine for error handling", + "outputs": [], + "source_origin": "materials/homework/week 1/Bonus_Exercise_Solved.py" + }, + { + "id": "hw-34b2e5ee0d", + "week": 1, + "cell_index": 5, + "cell_type": "code", + "topic": "strings", + "source": "# source: materials/homework/week 1/Exercise_1.4.py\nprint(2 * (x + '-3-') + x)", + "outputs": [], + "source_origin": "materials/homework/week 1/Exercise_1.4.py" + }, + { + "id": "hw-5cc01b0e90", + "week": 1, + "cell_index": 8, + "cell_type": "code", + "topic": "indexing", + "source": "# source: materials/homework/week 1/Exercise_1.7.py\nprint([x[3], x[0], x[2]])", + "outputs": [], + "source_origin": "materials/homework/week 1/Exercise_1.7.py" + }, + { + "id": "hw-d7dbe31ef7", + "week": 1, + "cell_index": 9, + "cell_type": "code", + "topic": "indexing", + "source": "# source: materials/homework/week 1/Exercise_1.8.py\nprint([[1 - x[0][0], 1 - x[0][1]], [1 - x[1][0], 1 - x[1][1]]])", + "outputs": [], + "source_origin": "materials/homework/week 1/Exercise_1.8.py" + }, + { + "id": "hw-57fbc30ac8", + "week": 1, + "cell_index": 10, + "cell_type": "code", + "topic": "slicing", + "source": "# source: materials/homework/week 1/Exercise_1.9.py\nleft = x.index(15) + 1\nremainder_x = x[left:]\nright = left + remainder_x.index(15)\nprint(x[left:right])", + "outputs": [], + "source_origin": "materials/homework/week 1/Exercise_1.9.py" + } + ], + "homework_recommended_ids": [ + "hw-4d85ae1fd0", + "hw-34b2e5ee0d", + "hw-5cc01b0e90" ] - } - }, - { - "id": "w2-dictionaries-and-mappings", - "topic": "Dictionaries and Mappings", - "canonical_topic": "w2-dictionaries-and-mappings", - "weeks": [ - 2 - ], - "week_id": "week-2", - "topic_meta": { - "week": 2, - "week_id": "week-2", - "week_title": "Week 2", - "topic_id": "w2-dictionaries-and-mappings", - "topic_title": "Dictionaries and Mappings", - "topic_order": 1 }, "subtopics": [ { - "id": "w2-dictionaries-and-mappings-core", - "title": "Creation, Lookup, Updates, and Key Constraints", - "order": 1, - "summary": "Dicts map unique immutable keys to values. `key in d` checks keys, `d[key]` looks up a value, and `.items()` gives `(key, value)` pairs for loops.", + "id": "w1-sequences-and-access-core", "item_ids": { - "lecture_snippet_ids": [ - "ks-65c4de2e9d", - "ks-adb6d9f967" - ], "exam_question_ids": [ - "exam-trial_midterm-2-w2-dictionaries-and-mappings", - "exam-trial_midterm-8-w2-dictionaries-and-mappings", - "exam-trial_midterm-10-w2-dictionaries-and-mappings", - "exam-trial_midterm-19-w2-dictionaries-and-mappings", - "exam-trial_midterm-23-w2-dictionaries-and-mappings", - "exam-midterm_2023-5-w2-dictionaries-and-mappings", - "exam-midterm_2023-6-w2-dictionaries-and-mappings", - "exam-midterm_2023-7-w2-dictionaries-and-mappings", - "exam-midterm_2023-8-w2-dictionaries-and-mappings", - "exam-midterm_2024-7-w2-dictionaries-and-mappings", - "exam-midterm_2024-8-w2-dictionaries-and-mappings", - "exam-midterm_2024-10-w2-dictionaries-and-mappings", - "exam-midterm_2024-11-w2-dictionaries-and-mappings", - "exam-midterm_2024-12-w2-dictionaries-and-mappings", - "exam-extra_practice-3-w2-dictionaries-and-mappings", - "exam-extra_practice-4-w2-dictionaries-and-mappings", - "exam-extra_practice-5-w2-dictionaries-and-mappings", - "exam-extra_practice-8-w2-dictionaries-and-mappings", - "exam-extra_practice-12-w2-dictionaries-and-mappings", - "exam-Trial final - Introduction to Python - 22/23-4-w2-dictionaries-and-mappings", - "exam-Trial final - Introduction to Python - 22/23-5-w2-dictionaries-and-mappings", - "exam-Trial final - Introduction to Python - 22/23-6-w2-dictionaries-and-mappings", - "exam-trial-final-exam-py22-4-w2-dictionaries-and-mappings", - "exam-trial-final-exam-py22-5-w2-dictionaries-and-mappings", - "exam-trial-final-exam-py22-6-w2-dictionaries-and-mappings", - "exam-Resit 22/23-7-w2-dictionaries-and-mappings" - ], - "notebook_snippet_ids": [ - "cs-f3df72fba8", - "cs-38e347e22f", - "cs-68a2fd332d", - "cs-d7d0d4e39b", - "cs-e2f05091db", - "cs-93d5411e58", - "cs-0663a1bed9", - "cs-b1d67e0aee" + "exam-extra_practice-6-w1-sequences-and-access", + "exam-intro_python_sample_final_24_25-18-w2-conditions" ], "example_ids": [ "ai-example-1", @@ -3138,213 +2635,895 @@ "ai-example-4", "ai-example-5", "ai-example-6", - "ai-example-7", - "ai-example-8" + "ai-example-7" ], "key_point_ids": [ "kp-1", "kp-2" + ], + "lecture_snippet_ids": [ + "ks-685cd3d828", + "ks-be78ccac04" + ], + "notebook_snippet_ids": [ + "cs-60dd1a8d2c", + "cs-0af6442b99", + "cs-85d755c5e8", + "cs-8a4ee4419d", + "cs-7ac6156d67", + "cs-15d46dcc2c", + "cs-ab9dc084b6", + "cs-59038bcffa", + "cs-curated-hw-seq-nth-occurrence", + "cs-curated-hw-seq-slice-between-sentinels" ] - } + }, + "order": 1, + "summary": "Use `seq[start:stop:step]` with stop excluded. Negative indices count from the end, and `range(start, stop, step)` follows the same stop-excluded rule.", + "title": "Indexing, Slicing, and range()" } ], - "exam_stats": { - "total_hits": 26, - "by_exam": { - "extra_practice": 5, - "midterm_2024": 5, - "trial_midterm": 5, - "midterm_2023": 4, - "Trial final - Introduction to Python - 22/23": 3, - "trial-final-exam-py22": 3, - "Resit 22/23": 1 - }, - "coverage_count": 7 + "topic": "Sequences and Access", + "topic_meta": { + "week": 1, + "week_id": "week-1", + "week_title": "Week 1", + "topic_id": "w1-sequences-and-access", + "topic_title": "Sequences and Access", + "topic_order": 4 }, - "related_topics": [ - "Creation, Lookup, Updates, and Key Constraints" - ], "trap_patterns": [ { - "pattern": "dict to tuple gives keys only", - "trap": "tuple({1:'a',2:'b'}) → (1,2) — only keys, not values or items", + "pattern": "str.upper() / string methods don't modify in place", + "trap": "s.upper() returns a new string; s is unchanged. Must do s = s.upper()", + "weeks": [ + 1 + ], + "appears_in_exams": [ + "trial_midterm", + "midterm_2023" + ] + }, + { + "pattern": "range() and slicing both exclusive at stop", + "trap": "range(1,10,3)→[1,4,7] not including 10; l[2:7] goes up to but not including index 7", "weeks": [ + 1, 2 ], "appears_in_exams": [ - "trial_midterm" + "trial_midterm", + "extra_practice" ] }, { - "pattern": "RuntimeError: dictionary changed size during iteration", - "trap": "Adding or deleting dict entries while iterating over it causes RuntimeError", + "pattern": "Negative slicing with step=-2", + "trap": "l[::-2] starts from last element going backwards with step 2. l[::2][::-1] first takes every other starting from 0, then reverses — different result", "weeks": [ - 3 + 1 ], "appears_in_exams": [ - "midterm_2024" + "extra_practice" ] } ], - "sections": { - "lecture_snippets": [ - { - "id": "ks-65c4de2e9d", - "week": 2, - "source": "materials/lectures/Lecture Week 2.md", - "source_type": "lecture", - "topic": "Dictionaries and Mappings", - "subtopic_id": "w2-dictionaries-and-mappings-core", - "subtopic_title": "Creation, Lookup, Updates, and Key Constraints", - "title": "Dictionaries", - "explanation": "Sets of key:value pairs. Keys must be unique and immutable (hashable). Dictionaries are unordered for equality ({1:1,2:2}=={2:2,1:1} is True). Cannot be sorted. You can check membership with 'in' — this checks KEYS only. Keys() gives key sequence, values() gives value sequence, items() gives tuples.", - "code_examples": [ - { - "description": "Creating and using dicts", - "code": "capitals = {}\ncapitals = dict()\ncapitals = {'Andorra': 'Andorra la Vella', 'Belgium': 'Brussels'}\nprint(capitals['Belgium']) # Brussels\ndel(capitals['Belgium']) # delete key\ncapitals['Netherlands'] = 'Amsterdam' # insert/update\ncapitals.update({'France': 'Paris'}) # insert/update multiple" - }, - { - "description": "Dict membership checks KEYS, not values", - "code": "d = {1: 4, 2: 3}\nprint(1 in d) # True (1 is a key)\nprint(4 in d) # False (4 is a value, not a key)" - }, - { - "description": "Creating dict from two lists", - "code": "l1 = [1, 2, 3, 4]\nl2 = [1, 4, 9, 16]\nsquares = dict(zip(l1, l2))\nprint(squares) # {1:1, 2:4, 3:9, 4:16}" - }, - { - "description": "Dict equality ignores order", - "code": "print({1:1, 2:2} == {2:2, 1:1}) # True\nprint([1,2] == [2,1]) # False" - } - ] - }, - { - "id": "ks-adb6d9f967", - "week": 2, - "source": "materials/lectures/Lecture Week 2.md", - "source_type": "lecture", - "topic": "Dictionaries and Mappings", - "subtopic_id": "w2-dictionaries-and-mappings-core", - "subtopic_title": "Creation, Lookup, Updates, and Key Constraints", - "title": "Looping over dictionaries", - "explanation": ".keys() → key sequence. .values() → value sequence. .items() → sequence of (key, value) tuples. 'for key in dict' is the same as 'for key in dict.keys()'.", - "code_examples": [ + "week_id": "week-1", + "weeks": [ + 1 + ] + }, + { + "id": "w1-functions-and-imports", + "topic": "Functions and Imports", + "canonical_topic": "w1-functions-and-imports", + "weeks": [ + 1 + ], + "week_id": "week-1", + "topic_meta": { + "week": 1, + "week_id": "week-1", + "week_title": "Week 1", + "topic_id": "w1-functions-and-imports", + "topic_title": "Functions and Imports", + "topic_order": 5 + }, + "subtopics": [ + { + "id": "w1-functions-and-imports-core", + "title": "Built-ins Intro, Functions, and Modules", + "order": 1, + "summary": "`import x` keeps the module name, `from x import y` brings `y` into scope, and `as` renames. Call functions with `()`, and keep `print` separate from returned values.", + "item_ids": { + "lecture_snippet_ids": [ + "ks-f43422a4cf", + "ks-b6a39f66a2" + ], + "exam_question_ids": [ + "exam-midterm_2023-12-w1-functions-and-imports", + "exam-midterm_2024-15-w1-functions-and-imports", + "exam-midterm_2024-16-w1-functions-and-imports", + "exam-Resit 22/23-5-w1-functions-and-imports", + "exam-intro_python_sample_final_24_25-24-w2-conditions" + ], + "notebook_snippet_ids": [ + "cs-beb6591b24", + "cs-6d0d650063", + "cs-4155022ebf", + "cs-23b2cfd4d6", + "cs-5b89a10dcd", + "cs-c25503e5db", + "cs-8a006d887d", + "cs-214144c1f0" + ], + "example_ids": [ + "ai-example-1", + "ai-example-2", + "ai-example-3", + "ai-example-4", + "ai-example-5", + "ai-example-6", + "ai-example-8" + ], + "key_point_ids": [ + "kp-1", + "kp-2" + ] + } + } + ], + "exam_stats": { + "total_hits": 4, + "by_exam": { + "midterm_2024": 2, + "Resit 22/23": 1, + "midterm_2023": 1 + }, + "coverage_count": 3 + }, + "related_topics": [ + "Built-ins Intro, Functions, and Modules" + ], + "trap_patterns": [ + { + "pattern": "Implicit return None", + "trap": "Function without return statement, or where return is not reached, returns None. print(func()) will print None.", + "weeks": [ + 3 + ], + "appears_in_exams": [ + "trial_midterm", + "extra_practice" + ] + } + ], + "sections": { + "lecture_snippets": [ + { + "id": "ks-f43422a4cf", + "week": 1, + "source": "materials/lectures/Lecture Week 1.md", + "source_type": "lecture", + "topic": "Functions and Imports", + "subtopic_id": "w1-functions-and-imports-core", + "subtopic_title": "Built-ins Intro, Functions, and Modules", + "title": "Importing packages", + "explanation": "Multiple import styles. 'import X' makes X available. 'import X as Y' renames. 'from X import Z' brings Z directly into namespace. 'from X import Z as W' renames. Once you use 'as', the original name is no longer accessible.", + "code_examples": [ { - "description": "Looping over dict", - "code": "capitals = {'Andorra': 'Andorra la Vella', 'Belgium': 'Brussels'}\nfor key in capitals.keys():\n print(key)\nfor val in capitals.values():\n print(val)\nfor key, value in capitals.items():\n print(key, value)\n# These two are equivalent:\nfor key in capitals:\nfor key in capitals.keys():" + "description": "Import styles", + "code": "import numpy\nnumpy.random.randint(1, 10) # works\n\nimport numpy as np\nnp.random.randint(1, 10) # works\nnumpy.random.randint(1, 10) # ERROR\n\nfrom numpy.random import randint\nrandint(1, 10) # works\n\nfrom numpy.random import randint as rnd\nrnd(1, 10) # works\nrandint(1, 10) # ERROR" } ] + }, + { + "id": "ks-b6a39f66a2", + "week": 1, + "source": "materials/notebooks/Notebook Week 1.ipynb", + "source_type": "notebook", + "topic": "Functions and Imports", + "subtopic_id": "w1-functions-and-imports-core", + "subtopic_title": "Built-ins Intro, Functions, and Modules", + "title": "intro", + "explanation": "### Print is a function and tells Python to output the argument (that what is between the brackets after the function name) on your screen\n
      • A function is a grouping of code that can perform a certain task and can be re-used \n
      • Print is a built-in function, that is a function that is part of the standard implementation of Python. Built-in fuctions like any function, can be used by calling their name. Built-in functions are already copied to your computer and the names of some of them like print, don't need to be imported\n
      • User functions are functions defined by you or other people that are not part of the standard Python implementation. (You will learn how to write your own…", + "code_examples": [] } ], "exam_questions": [ { - "id": "exam-trial_midterm-2-w2-dictionaries-and-mappings", - "exam_label": "trial_midterm", - "exam_source": "materials/exams/trial midterm.pdf", - "year": "2024-2025", - "number": 2, - "week": 2, - "topic": "dictionary / dict / key value", - "subtopic_id": "w2-dictionaries-and-mappings-core", - "subtopic_title": "Creation, Lookup, Updates, and Key Constraints", - "question": "Suppose you have a dictionary called characters, of which keys are strings and values are lists of strings.", - "code_context": "characters = {'first' : ['a', 'b', '1', 'c', '5'],\n'second': ['d', '2', 'e', '6', 'f'],\n'third' : ['3', 'g', '7', 'h', 'i']}\nYou want to modify the dictionary such that all the elements in the value lists are only character strings and not numeric\nstrings.\nThe intended output should look like this:\ncharacters = {'first': ['a', 'b', 'c'],\n'second': ['d', 'e', 'f'],\n'third': ['g', 'h', 'i']}\nWhich of the following programs will work as intended?\nHints:\nThe remove() list method removes the first occurrence of the element with the specified value.\nThe isnumeric() string method returns True if all the characters are numeric (0-9), otherwise False.\nA for array in characters.values():\nfor element in array:\nif element.isnumeric():\narray.remove(element)\nB for array in characters.values():\nfor index, element in enumerate(array):\nif element.isnumeric():\ndel array[index]\nC for key, value in characters.items():\nfor element in value:\nif element.isnumeric():\ndel value[value.index(element)]\nD All of the programs will work as intended.", - "options": {}, - "correct": "", - "explanation": "" - }, - { - "id": "exam-trial_midterm-8-w2-dictionaries-and-mappings", - "exam_label": "trial_midterm", - "exam_source": "materials/exams/trial midterm.pdf", - "year": "2024-2025", - "number": 8, - "week": 2, - "topic": "dictionary / dict", - "subtopic_id": "w2-dictionaries-and-mappings-core", - "subtopic_title": "Creation, Lookup, Updates, and Key Constraints", - "question": "Suppose you have the following dictionary:\nlibrary = {\"books\": 5,\n\"genres\": ['action', 'romance', 'thriller', 'classics']}\nYou want to:\n- add a key \"years\", of which the value is a list of strings that are the years of publication, i.e., [\"1932\" , \"2012\", \"1899\",\n\"2000\", \"1984\"],\n- change the value of the key \"books\" to 6.\nThe new value of the dictionary library should be:\n{\"books\" : 6,\n\"genres\" : ['action', 'romance', 'thriller', 'classics'],\n\"years\" : [\"1932\" , \"2012\", \"1899\", \"2000\", \"1984\"]}\nWhich of the programs below will work as intended?\nA library[\"books\"] = 6\nlibrary.update({\"years\": [\"1932\" , \"2012\", \"1899\", \"2000\", \"1984\"]})\nB library[\"books\"] = 6\nlibrary[\"years\"] = [\"1932\" , \"2012\", \"1899\", \"2000\", \"1984\"]\nC Both of the given options\nD None of the given options", - "code_context": "Suppose you have the following dictionary:\nlibrary = {\"books\": 5,\n\"genres\": ['action', 'romance', 'thriller', 'classics']}\nYou want to:\n- add a key \"years\", of which the value is a list of strings that are the years of publication, i.e., [\"1932\" , \"2012\", \"1899\",\n\"2000\", \"1984\"],\n- change the value of the key \"books\" to 6.\nThe new value of the dictionary library should be:\n{\"books\" : 6,\n\"genres\" : ['action', 'romance', 'thriller', 'classics'],\n\"years\" : [\"1932\" , \"2012\", \"1899\", \"2000\", \"1984\"]}\nWhich of the programs below will work as intended?\nA library[\"books\"] = 6\nlibrary.update({\"years\": [\"1932\" , \"2012\", \"1899\", \"2000\", \"1984\"]})\nB library[\"books\"] = 6\nlibrary[\"years\"] = [\"1932\" , \"2012\", \"1899\", \"2000\", \"1984\"]\nC Both of the given options\nD None of the given options", - "options": {}, - "correct": "", - "explanation": "" - }, - { - "id": "exam-trial_midterm-10-w2-dictionaries-and-mappings", - "exam_label": "trial_midterm", - "exam_source": "materials/exams/trial midterm.pdf", - "year": "2024-2025", - "number": 10, - "week": 2, - "topic": "dictionary / dict", - "subtopic_id": "w2-dictionaries-and-mappings-core", - "subtopic_title": "Creation, Lookup, Updates, and Key Constraints", - "question": "Suppose you have the following dictionary:\nx = {1: 10, 2: 20, 3: 30, 4: 40}\nWhat will the following line of code print?\nprint(list(x.values()) + list(x.keys()))\nA This code will result in an error because you cannot concatenate two lists using the + operator.\nB [10, 20, 30, 40, 1, 2, 3, 4]\nC [11, 22, 33, 44]\nD [(1, 10), (2, 20), (3, 30), (4, 40)]", - "code_context": "Suppose you have the following dictionary:\nx = {1: 10, 2: 20, 3: 30, 4: 40}\nWhat will the following line of code print?\nprint(list(x.values()) + list(x.keys()))\nA This code will result in an error because you cannot concatenate two lists using the + operator.\nB [10, 20, 30, 40, 1, 2, 3, 4]\nC [11, 22, 33, 44]\nD [(1, 10), (2, 20), (3, 30), (4, 40)]", + "id": "exam-midterm_2023-12-w1-functions-and-imports", + "exam_label": "midterm_2023", + "exam_source": "materials/exams/2023.pdf", + "year": "2022-2023", + "number": 12, + "week": 1, + "topic": "function", + "subtopic_id": "w1-functions-and-imports-core", + "subtopic_title": "Built-ins Intro, Functions, and Modules", + "question": "You want to write a program to calculate your income tax for 2023.", + "code_context": "Suppose your country imposes the following tax brackets:\nBracket Tax Taxable income\nrate Over Not over\n1 10% $0 $11,000\n2 12% $11,000 $45,000\n3 22% $45,000 $95,000\n4 32% $95,000\nIf your gross income is $50,000, you will pay 10% tax on the first $11,000, 12% tax on the next $34,000 and 22% tax on the last $5,000.\nWhich of the following function will return the output containing your net_income and your total_tax given your gross_income?\nFor example:\nIf we call the function as:\nincome_tax_calculator(50000)\nit should return:\n{'total_tax': 6280.0, 'net_income': 43720.0}\nA def income_tax_calculator(gross_income):\nresults = {}\nrate_1 = 0.10\nrate_2 = 0.12\nrate_3 = 0.22\nrate_4 = 0.32\nbracket_1 = 11000\nbracket_2 = 45000 - 11000\nbracket_3 = 95000 - 45000\nif gross_income > 95000:\ntotal_tax = ((gross_income - 95000) * rate_4) + (bracket_3 * rate_3) + (bracket_2 * rate_2)\n+ (bracket_1 * rate_1)\nelif 95000 >= gross_income > 45000:\ntotal_tax = ((gross_income - 45000) * rate_3) + (bracket_2 * rate_2) + (bracket_1 * rate_1)\nelif 45000 >= gross_income > 11000:\ntotal_tax = ((gross_income - 11000) * rate_2) + (bracket_1 * rate_1)\nelse:\ntotal_tax = gross_income * rate_1\nnet_income = gross_income - total_tax\nresults['total_tax'] = round(total_tax, 2)\nresults['net_income'] = round(net_income, 2)\nreturn results\nB def income_tax_calculator(gross_income):\n​ results = {}\nrate_1 = 0.10\nrate_2 = 0.12\nrate_3 = 0.22\nrate_4 = 0.32\nbracket_1 = 11000\nbracket_2 = 45000 - 11001\nbracket_3 = 95000 - 45001\ntotal_tax = (gross_income - 95001) * rate_4 + (bracket_3 * rate_3) + (bracket_2 * rate_2) +\n(bracket_1 * rate_1)\nnet_income = lambda gross_income, total_tax: gross_income - total_tax\nresults['total_tax'] = round(total_tax, 2)\nresults['net_income'] = round(net_income, 2)\nreturn results\nC def income_tax_calculator(gross_income):\n​ results = {}\nrate_1 = 0.10\nrate_2 = 0.12\nrate_3 = 0.22\nrate_4 = 0.32\nif gross_income <= 11000:\ntotal_tax = gross_income * rate_1\nif 45000 > gross_income > 11000:\ntotal_tax += (45000 - gross_income) * rate_2\nif 95000 > gross_income > 45000:\ntotal_tax += (95000 - gross_income) * rate_3\nelse:\ntotal_tax += (gross_income - 95000) * rate_4\nnet_income = gross_income - total_tax\nresults['total_tax'] = total_tax\nresults['net_income'] = net_income\nreturn(total_tax, net_income)\nD All of three functions will work as intended.", "options": {}, "correct": "", "explanation": "" }, { - "id": "exam-trial_midterm-19-w2-dictionaries-and-mappings", - "exam_label": "trial_midterm", - "exam_source": "materials/exams/trial midterm.pdf", - "year": "2024-2025", - "number": 19, - "week": 2, - "topic": "dictionary / dict", - "subtopic_id": "w2-dictionaries-and-mappings-core", - "subtopic_title": "Creation, Lookup, Updates, and Key Constraints", - "question": "Suppose you have the following function:\ndef my_count_function(string):\ncounts = {}\nfor letter in string:\nif letter in counts:\ncounts[letter] += 1\nelse:\ncounts[letter] = 1\nreturn counts\nAnd you create the following two dictionaries:\napple_count = my_count_function(\"apple\")\npeach_count = my_count_function(\"peach\")\nWhich of the code snippets of code below prints something different than the other code snippets?\nA print(len(apple_count.keys()))\nB print(len(peach_count.keys()))\nC print(sum(apple_count.values()))\nD print(sum(peach_count.values()))", - "code_context": "Suppose you have the following function:\ndef my_count_function(string):\ncounts = {}\nfor letter in string:\nif letter in counts:\ncounts[letter] += 1\nelse:\ncounts[letter] = 1\nreturn counts\nAnd you create the following two dictionaries:\napple_count = my_count_function(\"apple\")\npeach_count = my_count_function(\"peach\")\nWhich of the code snippets of code below prints something different than the other code snippets?\nA print(len(apple_count.keys()))\nB print(len(peach_count.keys()))\nC print(sum(apple_count.values()))\nD print(sum(peach_count.values()))", + "id": "exam-midterm_2024-15-w1-functions-and-imports", + "exam_label": "midterm_2024", + "exam_source": "materials/exams/2024.pdf", + "year": "2023-2024", + "number": 15, + "week": 1, + "topic": "function", + "subtopic_id": "w1-functions-and-imports-core", + "subtopic_title": "Built-ins Intro, Functions, and Modules", + "question": "Consider the following code snippet:\ndef main(lst, condition=lambda x: x):\ny = []\nfor x in lst:\nif condition(x):\ny.append(x)\nreturn y\nWhat will this function return, when called in the following way:\nmain([1, 2, 3, 4, 5, 6, 7, 8, 9, 10], lambda x: x % 2 != 0)\nA [1, 3, 5, 7, 9]\nB [2, 4, 6, 8, 10]\nC [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]\nD None", + "code_context": "Consider the following code snippet:\ndef main(lst, condition=lambda x: x):\ny = []\nfor x in lst:\nif condition(x):\ny.append(x)\nreturn y\nWhat will this function return, when called in the following way:\nmain([1, 2, 3, 4, 5, 6, 7, 8, 9, 10], lambda x: x % 2 != 0)\nA [1, 3, 5, 7, 9]\nB [2, 4, 6, 8, 10]\nC [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]\nD None", "options": {}, "correct": "", "explanation": "" }, { - "id": "exam-trial_midterm-23-w2-dictionaries-and-mappings", - "exam_label": "trial_midterm", - "exam_source": "materials/exams/trial midterm.pdf", - "year": "2024-2025", - "number": 23, - "week": 2, - "topic": "dictionary / dict / key value", - "subtopic_id": "w2-dictionaries-and-mappings-core", - "subtopic_title": "Creation, Lookup, Updates, and Key Constraints", - "question": "You have to write a function called summarize which take a list of integers as an argument.", - "code_context": "The function should return a dictionary with the following key-value pairs:\namount: the number of the integers from the input list\nsmallest: the smallest integer from the input list\nlargest: the largest integer from the input list\ntotal: the sum of all integers from the input list\nWhich of the following functions will achieve what you need?\nA def summarize(x):\ny = {}\nx['amount'] = len(y)\nx['smallest'] = min(y)\nx['largest'] = max(y)\nx['total'] = sum(y)\nreturn x\nB def summarize(x):\ny = {}\ntotal = 0\nfor integer in x:\ny['amount'] = len(x)\nif integer == min(x):\ny['smallest'] = min(x)\nelif integer == max(x):\ny['largest'] = max(x)\nelse:\ny['total'] += integer\nreturn y\nC def summarize(x):\ny = {}\nfor integer in x:\nif integer == min(x):\ny['smallest'] == min(x)\nelif integer == max(x):\ny['largest'] == max(x)\nelse:\ny['amount'] == x.count()\ny['total'] == sum(x)\nreturn y\nD None of the functions will work as needed.", + "id": "exam-midterm_2024-16-w1-functions-and-imports", + "exam_label": "midterm_2024", + "exam_source": "materials/exams/2024.pdf", + "year": "2023-2024", + "number": 16, + "week": 1, + "topic": "function", + "subtopic_id": "w1-functions-and-imports-core", + "subtopic_title": "Built-ins Intro, Functions, and Modules", + "question": "You need to write a function called weather_alert that accepts a string argument, which is a color code of the weather alert system.", + "code_context": "Your function should return one of the following lines to inform the citizens of what to do depending on the color:\nIf the color is red, return: \"Take action to protect against severe condition.\"\nIf the color is orange, return: \"Be prepared for damages.\"\nIf the color is yellow, return: \"Be alert for potential hazard.\"\nFor any other colors, return: \"No warning.\"\nWhich of the following program will do want you need?\nA def weather_alert(color):\nif color == \"red\":\nreturn \"Take action to protect against severe condition.\"\nelif color == \"orange\":\nreturn \"Be prepared for damages.\"\nelif color == \"yellow\":\nreturn \"Be alert for potential hazard.\"\nreturn \"No warning.\"\nB def weather_alert(color):\nif color == \"red\":\nprint(\"Take action to protect against severe condition.\")\nelif color == \"orange\":\nprint(\"Be prepared for damages.\")\nelif color == \"yellow\":\nprint(\"Be alert for potential hazard.\")\nelse:\nprint(\"No warning.\")\nC def weather_alert(color):\nif color == \"red\":\nreturn \"Take action to protect against severe condition.\"\nelif color == \"orange\":\nreturn \"Be prepared for damages.\"\nelif color == \"yellow\":\nreturn \"Be alert for potential hazard.\"\nelif color == \"green\":\nreturn \"No warning.\"\nD All of the programs should work as intended.", "options": {}, "correct": "", "explanation": "" }, { - "id": "exam-midterm_2023-5-w2-dictionaries-and-mappings", - "exam_label": "midterm_2023", - "exam_source": "materials/exams/2023.pdf", + "id": "exam-Resit 22/23-5-w1-functions-and-imports", + "exam_label": "Resit 22/23", + "exam_source": "materials/post_midterm/practice_exams_previous_years/resit-solutions-for-introduction-to-python-35761538.pdf", "year": "2022-2023", "number": 5, - "week": 2, - "topic": "dictionary / dict / key value", - "subtopic_id": "w2-dictionaries-and-mappings-core", - "subtopic_title": "Creation, Lookup, Updates, and Key Constraints", - "question": "What is the output of the program below?", - "code_context": "x = {1: 10, 2: 20, 3: 30, 4: 40, 5: 50}\ny = {1: 50, 2: 40, 3: 30, 4: 20, 5: 10}\nz = x.copy()\nfor key, value in x.items():\nif key in y:\nif value <= y[key]:\nz[key] = y[key]\nz[key] = y[key]\nprint(z)\nA {1: 50, 2: 40, 3: 30, 4: 20, 5: 10}\nB {1: 10, 2: 20, 3: 30, 4: 40, 5: 50}\nC None of the given options\nD {}", - "options": {}, - "correct": "", - "explanation": "" + "week": 1, + "topic": "3_Function_Built-in_2", + "subtopic_id": "w1-functions-and-imports-core", + "subtopic_title": "Built-ins Intro, Functions, and Modules", + "question": "Suppose you have a list called x. Which of the following code segments will print the following list?\n[5, 4, 3, 2, 1]", + "code_context": "x = [1, 1, 2, 2, 3, 3, 4, 4, 5, 5]", + "options": { + "a": "y = list(set(x))\nprint(sorted(y, reverse = True))", + "b": "print(x[::-2])", + "c": "Both lines of code will print that output.", + "d": "Neither line of code will print that output." + }, + "correct": "c", + "explanation": "Option A extracts unique elements with `set(x)`, resulting in `{1, 2, 3, 4, 5}`, then sorts them in reverse order, giving `[5, 4, 3, 2, 1]`. Option B uses list slicing `x[::-2]` which steps backwards through `x` by 2, retrieving indices -1, -3, -5, -7, and -9, which correspond to 5, 4, 3, 2, 1. Thus, both A and B are correct." }, { - "id": "exam-midterm_2023-6-w2-dictionaries-and-mappings", - "exam_label": "midterm_2023", - "exam_source": "materials/exams/2023.pdf", - "year": "2022-2023", - "number": 6, - "week": 2, - "topic": "dictionary / dict", - "subtopic_id": "w2-dictionaries-and-mappings-core", - "subtopic_title": "Creation, Lookup, Updates, and Key Constraints", - "question": "Suppose you have the following dictionary:\nsample_dict = {\n\"name\": \"Kim\",\n\"age\": 25,\n\"birthdate\": \"3-2-1998\",\n\"city\": \"Amsterdam\"}\nSuppose you want to create a dictionary that only contains the keys 'name' and 'city'.\nWhich of the following code snippets return(s) the desired dictionary?\nA keys = [\"name\", \"city\"]\nnew_dict = {}\nfor k in keys:\nnew_dict[k] = sample_dict[k]\nnew_dict\nB keys = [\"age\", \"birthdate\"]\nnew_dict = {}\nnew_keys = sample_dict.keys() - keys\nfor k in new_keys:\nnew_dict[k] = sample_dict[k]\nnew_dict\nC None of the given options\nD Both of the given options", - "code_context": "Suppose you have the following dictionary:\nsample_dict = {\n\"name\": \"Kim\",\n\"age\": 25,\n\"birthdate\": \"3-2-1998\",\n\"city\": \"Amsterdam\"}\nSuppose you want to create a dictionary that only contains the keys 'name' and 'city'.\nWhich of the following code snippets return(s) the desired dictionary?\nA keys = [\"name\", \"city\"]\nnew_dict = {}\nfor k in keys:\nnew_dict[k] = sample_dict[k]\nnew_dict\nB keys = [\"age\", \"birthdate\"]\nnew_dict = {}\nnew_keys = sample_dict.keys() - keys\nfor k in new_keys:\nnew_dict[k] = sample_dict[k]\nnew_dict\nC None of the given options\nD Both of the given options", - "options": {}, + "id": "exam-intro_python_sample_final_24_25-24-w2-conditions", + "exam_label": "intro_python_sample_final_24_25", + "exam_source": "materials/post_midterm/Sample Final plus answers.pdf", + "year": "2024", + "number": 24, + "week": 1, + "topic": "Modules", + "subtopic_id": "w1-functions-and-imports-core", + "subtopic_title": "Built-ins Intro, Functions, and Modules", + "question": "Which script does NOT print the correct answer for the area of a circle?", + "code_context": "", + "options": { + "A": "import math; print(math.pi * r ** 2)", + "B": "from math import pi; print(pi * r ** 2)", + "C": "import math as constants; print(math.pi * r ** 2)", + "D": "from math import pi as constant; print(constant * r ** 2)" + }, + "correct": "C", + "explanation": "If math is imported as constants, it must be referred to as 'constants.pi'. 'math.pi' will no longer be available unless 'math' was also imported directly." + } + ], + "notebook_snippets": [ + { + "id": "cs-beb6591b24", + "week": 1, + "cell_index": null, + "cell_type": "code", + "source_type": "notebook", + "topic": "Functions and Imports", + "subtopic_id": "w1-functions-and-imports-core", + "subtopic_title": "Built-ins Intro, Functions, and Modules", + "title": "imports", + "source": "clear_names()\n\nimport extension as ex\ntry:\n print(ex.YEAR)\nexcept Exception as e:\n print(e)\n\ntry:\n print(extension.YEAR)\nexcept Exception as e:\n print(e)", + "outputs": [ + "2025\nname 'extension' is not defined" + ] + }, + { + "id": "cs-6d0d650063", + "week": 1, + "cell_index": null, + "cell_type": "code", + "source_type": "notebook", + "topic": "Functions and Imports", + "subtopic_id": "w1-functions-and-imports-core", + "subtopic_title": "Built-ins Intro, Functions, and Modules", + "title": "imports", + "source": "clear_names()\n\nimport extension\nimport extension as ex\ntry:\n print(ex.YEAR)\nexcept Exception as e:\n print(e)\n\ntry:\n print(extension.YEAR)\nexcept Exception as e:\n print(e)", + "outputs": [ + "2025\n2025" + ] + }, + { + "id": "cs-4155022ebf", + "week": 1, + "cell_index": null, + "cell_type": "code", + "source_type": "notebook", + "topic": "Functions and Imports", + "subtopic_id": "w1-functions-and-imports-core", + "subtopic_title": "Built-ins Intro, Functions, and Modules", + "title": "imports", + "source": "clear_names()\n\nfrom extension import create_absolute_year\ntry:\n print(create_absolute_year(1))\nexcept Exception as e:\n print(e)\n\ntry:\n print(YEAR)\nexcept Exception as e:\n print(e)", + "outputs": [ + "2026\nname 'YEAR' is not defined" + ] + }, + { + "id": "cs-23b2cfd4d6", + "week": 1, + "cell_index": null, + "cell_type": "code", + "source_type": "notebook", + "topic": "Functions and Imports", + "subtopic_id": "w1-functions-and-imports-core", + "subtopic_title": "Built-ins Intro, Functions, and Modules", + "title": "imports", + "source": "clear_names()\n\nfrom extension import create_absolute_year as cay\ntry:\n print(create_absolute_year(1))\nexcept Exception as e:\n print(e)\n\ntry:\n print(cay(1))\nexcept Exception as e:\n print(e)", + "outputs": [ + "name 'create_absolute_year' is not defined\n2026" + ] + }, + { + "id": "cs-5b89a10dcd", + "week": 1, + "cell_index": null, + "cell_type": "code", + "source_type": "notebook", + "topic": "Functions and Imports", + "subtopic_id": "w1-functions-and-imports-core", + "subtopic_title": "Built-ins Intro, Functions, and Modules", + "title": "imports", + "source": "clear_names()\ntry:\n print(YEAR)\nexcept Exception as e:\n print(Exception)\n\ntry:\n print(extension.YEAR)\nexcept Exception as e:\n print(e)\n\nimport extension\ntry:\n print(YEAR)\nexcept Exception as e:\n print(e)\n\ntry:\n print(extension.YEAR)\nexcept Exception as e:\n print(e)", + "outputs": [ + "\nname 'extension' is not defined\nname 'YEAR' is not defined\n2025" + ] + }, + { + "id": "cs-c25503e5db", + "week": 1, + "cell_index": null, + "cell_type": "code", + "source_type": "notebook", + "topic": "Functions and Imports", + "subtopic_id": "w1-functions-and-imports-core", + "subtopic_title": "Built-ins Intro, Functions, and Modules", + "title": "imports", + "source": "%%writefile extension.py\n# In this cell we create a python file and write that to the hard disk (either of your computer or to the cloud depending where you run your code.\n# We will import this file to show how to import the names of objects \n# into your Python program\nYEAR = 2025\ndef create_absolute_year(x):\n return YEAR + x", + "outputs": [ + "Overwriting extension.py" + ] + }, + { + "id": "cs-8a006d887d", + "week": 1, + "cell_index": null, + "cell_type": "code", + "source_type": "notebook", + "topic": "Functions and Imports", + "subtopic_id": "w1-functions-and-imports-core", + "subtopic_title": "Built-ins Intro, Functions, and Modules", + "title": "import dis", + "source": "#\nimport dis\ndef func():\n print('Hello World')\ndis.dis(func)", + "outputs": [] + }, + { + "id": "cs-214144c1f0", + "week": 1, + "cell_index": null, + "cell_type": "code", + "source_type": "notebook", + "topic": "Functions and Imports", + "subtopic_id": "w1-functions-and-imports-core", + "subtopic_title": "Built-ins Intro, Functions, and Modules", + "title": "from decimal import Decimal", + "source": "#\nfrom decimal import Decimal\nprint(Decimal('1.1') + Decimal('2.2'))", + "outputs": [] + } + ], + "ai_summary": { + "status": "curated", + "content": "`import x` keeps the module name, `from x import y` brings `y` into scope, and `as` renames. Call functions with `()`, and keep `print` separate from returned values.", + "generator": "lecture-first-build", + "model": null + }, + "ai_common_questions": { + "status": "curated", + "bullets": [ + "You want to write a program to calculate your income tax for 2023.", + "Consider the following code snippet:\ndef main(lst, condition=lambda x: x):\ny = []\nfor x in lst:\nif condition(x):\ny.append(x)\nreturn y\nWhat will this function return, when called in the following way:\nmain([1, 2, 3, 4, 5, 6, 7, 8, 9, 10], lambda x: x % 2 != 0)…", + "You need to write a function called weather_alert that accepts a string argument, which is a color code of the weather alert system.", + "Suppose you have a list called x. Which of the following code segments will print the following list?\n[5, 4, 3, 2, 1]", + "Function without return statement, or where return is not reached, returns None. print(func()) will print None." + ], + "items": [ + { + "id": "manual-import-names", + "summary": "How do different import forms change the names you can use locally?", + "detail": "`import math` gives `math.sqrt`, `import math as m` gives `m.sqrt`, and `from math import sqrt` gives `sqrt(...)` directly.", + "extra": "", + "code": "import math\nimport math as m\nfrom math import sqrt", + "table": null + }, + { + "id": "manual-print-vs-return", + "summary": "What is the difference between printing a value and returning a value from a function?", + "detail": "`print(x)` shows a value on screen. `return x` sends a value back to the caller so it can be stored, reused, or printed later.", + "extra": "", + "code": "def f(x):\n return x + 1\n\nprint(f(3))", + "table": null + }, + { + "id": "manual-implicit-none", + "summary": "What does a function return if it reaches the end without `return`?", + "detail": "Python returns `None` if no `return` statement is executed.", + "extra": "", + "code": "def f():\n print('hi')\n\nprint(f())", + "table": null + } + ], + "generator": "lecture-first-build", + "model": null + }, + "key_points_to_remember": [ + { + "id": "kp-1", + "text": "`import x` keeps the module name, `import x as y` renames it, and `from x import z` brings `z` into scope directly.", + "status": "curated", + "generator": "lecture-first-build", + "model": null, + "subtopic_id": "w1-functions-and-imports-core", + "subtopic_title": "Built-ins Intro, Functions, and Modules", + "details": [ + { + "id": "kp-1-d1", + "kind": "example", + "title": "Import styles", + "code": "import numpy\nnumpy.random.randint(1, 10) # works\n\nimport numpy as np\nnp.random.randint(1, 10) # works\nnumpy.random.randint(1, 10) # ERROR\n\nfrom numpy.random import randint\nrandint(1, 10) # works\n\nfrom numpy.random import randint as rnd\nrnd(1, 10) # works\nrandint(1, 10) # ERROR" + }, + { + "id": "kp-1-d2", + "kind": "table", + "title": "Dense reference table", + "table": { + "headers": [ + "Call", + "Use", + "Typical result" + ], + "rows": [ + [ + "int('123')", + "string to integer", + "123" + ], + [ + "float('123')", + "string to float", + "123.0" + ], + [ + "str(123.0)", + "number to string", + "'123.0'" + ], + [ + "round(x, 2)", + "round for display/checking", + "2 decimals" + ] + ] + } + } + ] + }, + { + "id": "kp-2", + "text": "Use `print(...)` to display a value. A function groups reusable code and may also return a value to its caller.", + "status": "curated", + "generator": "lecture-first-build", + "model": null, + "subtopic_id": "w1-functions-and-imports-core", + "subtopic_title": "Built-ins Intro, Functions, and Modules", + "details": [] + } + ], + "ai_examples": [ + { + "id": "ai-example-1", + "kind": "correct", + "title": "Import module under its original name", + "code": "import numpy\nnumpy.random.randint(1, 10) # works\n\nimport numpy as np\nnp.random.randint(1, 10) # works\nnumpy.random.randint(1, 10) # ERROR\n\nfrom numpy.random import randint\nrandint(1, 10) # works\n\nfrom numpy.random import randint as rnd\nrnd(1, 10) # works\nrandint(1, 10) # ERROR", + "why": "`import x` keeps the module name, `import x as y` renames it, and `from x import z` brings `z` into scope directly.", + "output": "", + "status": "curated", + "subtopic_id": "w1-functions-and-imports-core", + "subtopic_title": "Built-ins Intro, Functions, and Modules" + }, + { + "id": "ai-example-2", + "kind": "correct", + "title": "Direct import plus alias binds both names", + "code": "clear_names()\n\nimport extension as ex\ntry:\n print(ex.YEAR)\nexcept Exception as e:\n print(e)\n\ntry:\n print(extension.YEAR)\nexcept Exception as e:\n print(e)", + "why": "Keep track of which name is actually available after `import`, `from ... import ...`, or `as`.", + "output": "2025\nname 'extension' is not defined", + "status": "curated", + "subtopic_id": "w1-functions-and-imports-core", + "subtopic_title": "Built-ins Intro, Functions, and Modules" + }, + { + "id": "ai-example-3", + "kind": "correct", + "title": "from-import binds only the imported name", + "code": "clear_names()\n\nimport extension\nimport extension as ex\ntry:\n print(ex.YEAR)\nexcept Exception as e:\n print(e)\n\ntry:\n print(extension.YEAR)\nexcept Exception as e:\n print(e)", + "why": "Keep track of which name is actually available after `import`, `from ... import ...`, or `as`.", + "output": "2025\n2025", + "status": "curated", + "subtopic_id": "w1-functions-and-imports-core", + "subtopic_title": "Built-ins Intro, Functions, and Modules" + }, + { + "id": "ai-example-4", + "kind": "correct", + "title": "Aliased from-import uses the alias locally", + "code": "clear_names()\n\nfrom extension import create_absolute_year\ntry:\n print(create_absolute_year(1))\nexcept Exception as e:\n print(e)\n\ntry:\n print(YEAR)\nexcept Exception as e:\n print(e)", + "why": "Keep track of which name is actually available after `import`, `from ... import ...`, or `as`.", + "output": "2026\nname 'YEAR' is not defined", + "status": "curated", + "subtopic_id": "w1-functions-and-imports-core", + "subtopic_title": "Built-ins Intro, Functions, and Modules" + }, + { + "id": "ai-example-5", + "kind": "correct", + "title": "import module does not create bare globals", + "code": "clear_names()\n\nfrom extension import create_absolute_year as cay\ntry:\n print(create_absolute_year(1))\nexcept Exception as e:\n print(e)\n\ntry:\n print(cay(1))\nexcept Exception as e:\n print(e)", + "why": "Keep track of which name is actually available after `import`, `from ... import ...`, or `as`.", + "output": "name 'create_absolute_year' is not defined\n2026", + "status": "curated", + "subtopic_id": "w1-functions-and-imports-core", + "subtopic_title": "Built-ins Intro, Functions, and Modules" + }, + { + "id": "ai-example-6", + "kind": "correct", + "title": "Import module under its original name", + "code": "clear_names()\ntry:\n print(YEAR)\nexcept Exception as e:\n print(Exception)\n\ntry:\n print(extension.YEAR)\nexcept Exception as e:\n print(e)\n\nimport extension\ntry:\n print(YEAR)\nexcept Exception as e:\n print(e)\n\ntry:\n print(extension.YEAR)\nexcept Exception as e:\n print(e)", + "why": "Keep track of which name is actually available after `import`, `from ... import ...`, or `as`.", + "output": "\nname 'extension' is not defined\nname 'YEAR' is not defined\n2025", + "status": "curated", + "subtopic_id": "w1-functions-and-imports-core", + "subtopic_title": "Built-ins Intro, Functions, and Modules" + }, + { + "id": "ai-example-8", + "kind": "incorrect", + "title": "Income tax branches and return shape", + "code": "Suppose your country imposes the following tax brackets:\nBracket Tax Taxable income\nrate Over Not over\n1 10% $0 $11,000\n2 12% $11,000 $45,000\n3 22% $45,000 $95,000\n4 32% $95,000\nIf your gross income is $50,000, you will pay 10% tax on the first $11,000, 12% tax on the next $34,000 and 22% tax on the last $5,000.\nWhich of the following function will return the output containing your net_income and your total_tax given your gross_income?\nFor example:\nIf we call the function as:\nincome_tax_calculator(50000)\nit should return:\n{'total_tax': 6280.0, 'net_income': 43720.0}\nA def income_tax_calculator(gross_income):\nresults = {}\nrate_1 = 0.10\nrate_2 = 0.12\nrate_3 = 0.22\nrate_4 = 0.32\nbracket_1 = 11000\nbracket_2 = 45000 - 11000\nbracket_3 = 95000 - 45000\nif gross_income > 95000:\ntotal_tax = ((gross_income - 95000) * rate_4) + (bracket_3 * rate_3) + (bracket_2 * rate_2)\n+ (bracket_1 * rate_1)\nelif 95000 >= gross_income > 45000:\ntotal_tax = ((gross_income - 45000) * rate_3) + (bracket_2 * rate_2) + (bracket_1 * rate_1)\nelif 45000 >= gross_income > 11000:\ntotal_tax = ((gross_income - 11000) * rate_2) + (bracket_1 * rate_1)\nelse:\ntotal_tax = gross_income * rate_1\nnet_income = gross_income - total_tax\nresults['total_tax'] = round(total_tax, 2)\nresults['net_income'] = round(net_income, 2)\nreturn results\nB def income_tax_calculator(gross_income):\n​ results = {}\nrate_1 = 0.10\nrate_2 = 0.12\nrate_3 = 0.22\nrate_4 = 0.32\nbracket_1 = 11000\nbracket_2 = 45000 - 11001\nbracket_3 = 95000 - 45001\ntotal_tax = (gross_income - 95001) * rate_4 + (bracket_3 * rate_3) + (bracket_2 * rate_2) +\n(bracket_1 * rate_1)\nnet_income = lambda gross_income, total_tax: gross_income - total_tax\nresults['total_tax'] = round(total_tax, 2)\nresults['net_income'] = round(net_income, 2)\nreturn results\nC def income_tax_calculator(gross_income):\n​ results = {}\nrate_1 = 0.10\nrate_2 = 0.12\nrate_3 = 0.22\nrate_4 = 0.32\nif gross_income <= 11000:\ntotal_tax = gross_income * rate_1\nif 45000 > gross_income > 11000:\ntotal_tax += (45000 - gross_income) * rate_2\nif 95000 > gross_income > 45000:\ntotal_tax += (95000 - gross_income) * rate_3\nelse:\ntotal_tax += (gross_income - 95000) * rate_4\nnet_income = gross_income - total_tax\nresults['total_tax'] = total_tax\nresults['net_income'] = net_income\nreturn(total_tax, net_income)\nD All of three functions will work as intended.", + "why": "Check branch boundaries, rounding, and whether the function returns `{'total_tax': ..., 'net_income': ...}`.", + "output": "", + "status": "curated", + "subtopic_id": "w1-functions-and-imports-core", + "subtopic_title": "Built-ins Intro, Functions, and Modules" + } + ], + "recommended_ids": [ + "exam-intro_python_sample_final_24_25-24-w2-conditions", + "exam-Resit 22/23-5-w1-functions-and-imports", + "exam-midterm_2023-12-w1-functions-and-imports", + "exam-midterm_2024-15-w1-functions-and-imports", + "exam-midterm_2024-16-w1-functions-and-imports", + "ks-f43422a4cf", + "ks-b6a39f66a2", + "cs-beb6591b24", + "cs-6d0d650063" + ], + "homework_snippets": [], + "homework_recommended_ids": [] + } + }, + { + "id": "w2-dictionaries-and-mappings", + "topic": "Dictionaries and Mappings", + "canonical_topic": "w2-dictionaries-and-mappings", + "weeks": [ + 2 + ], + "week_id": "week-2", + "topic_meta": { + "week": 2, + "week_id": "week-2", + "week_title": "Week 2", + "topic_id": "w2-dictionaries-and-mappings", + "topic_title": "Dictionaries and Mappings", + "topic_order": 1 + }, + "subtopics": [ + { + "id": "w2-dictionaries-and-mappings-core", + "title": "Creation, Lookup, Updates, and Key Constraints", + "order": 1, + "summary": "Dicts map unique immutable keys to values. `key in d` checks keys, `d[key]` looks up a value, and `.items()` gives `(key, value)` pairs for loops.", + "item_ids": { + "lecture_snippet_ids": [ + "ks-65c4de2e9d", + "ks-adb6d9f967" + ], + "exam_question_ids": [ + "exam-trial_midterm-2-w2-dictionaries-and-mappings", + "exam-trial_midterm-8-w2-dictionaries-and-mappings", + "exam-trial_midterm-10-w2-dictionaries-and-mappings", + "exam-trial_midterm-19-w2-dictionaries-and-mappings", + "exam-trial_midterm-23-w2-dictionaries-and-mappings", + "exam-midterm_2023-5-w2-dictionaries-and-mappings", + "exam-midterm_2023-6-w2-dictionaries-and-mappings", + "exam-midterm_2023-7-w2-dictionaries-and-mappings", + "exam-midterm_2023-8-w2-dictionaries-and-mappings", + "exam-midterm_2024-7-w2-dictionaries-and-mappings", + "exam-midterm_2024-8-w2-dictionaries-and-mappings", + "exam-midterm_2024-10-w2-dictionaries-and-mappings", + "exam-midterm_2024-11-w2-dictionaries-and-mappings", + "exam-midterm_2024-12-w2-dictionaries-and-mappings", + "exam-extra_practice-3-w2-dictionaries-and-mappings", + "exam-extra_practice-4-w2-dictionaries-and-mappings", + "exam-extra_practice-5-w2-dictionaries-and-mappings", + "exam-extra_practice-8-w2-dictionaries-and-mappings", + "exam-extra_practice-12-w2-dictionaries-and-mappings", + "exam-Trial final - Introduction to Python - 22/23-4-w2-dictionaries-and-mappings", + "exam-Trial final - Introduction to Python - 22/23-5-w2-dictionaries-and-mappings", + "exam-Trial final - Introduction to Python - 22/23-6-w2-dictionaries-and-mappings", + "exam-trial-final-exam-py22-4-w2-dictionaries-and-mappings", + "exam-trial-final-exam-py22-5-w2-dictionaries-and-mappings", + "exam-trial-final-exam-py22-6-w2-dictionaries-and-mappings", + "exam-Resit 22/23-7-w2-dictionaries-and-mappings", + "exam-intro_python_sample_final_24_25-19-w3-defining-and-calling-functions", + "exam-intro_python_sample_final_24_25-20-w3-defining-and-calling-functions", + "exam-intro_python_sample_final_24_25-21-w3-defining-and-calling-functions" + ], + "notebook_snippet_ids": [ + "cs-f3df72fba8", + "cs-38e347e22f", + "cs-68a2fd332d", + "cs-d7d0d4e39b", + "cs-e2f05091db", + "cs-93d5411e58", + "cs-0663a1bed9", + "cs-b1d67e0aee", + "cs-curated-hw-dict-digit-frequency", + "cs-curated-hw-dict-delete-shared-keys", + "cs-curated-hw-dict-project-values-sorted-keys" + ], + "example_ids": [ + "ai-example-1", + "ai-example-2", + "ai-example-4", + "ai-example-5", + "ai-example-6", + "ai-example-7", + "ai-example-8" + ], + "key_point_ids": [ + "kp-1", + "kp-2" + ] + } + } + ], + "exam_stats": { + "total_hits": 26, + "by_exam": { + "extra_practice": 5, + "midterm_2024": 5, + "trial_midterm": 5, + "midterm_2023": 4, + "Trial final - Introduction to Python - 22/23": 3, + "trial-final-exam-py22": 3, + "Resit 22/23": 1 + }, + "coverage_count": 7 + }, + "related_topics": [ + "Creation, Lookup, Updates, and Key Constraints" + ], + "trap_patterns": [ + { + "pattern": "dict to tuple gives keys only", + "trap": "tuple({1:'a',2:'b'}) → (1,2) — only keys, not values or items", + "weeks": [ + 2 + ], + "appears_in_exams": [ + "trial_midterm" + ] + }, + { + "pattern": "RuntimeError: dictionary changed size during iteration", + "trap": "Adding or deleting dict entries while iterating over it causes RuntimeError", + "weeks": [ + 3 + ], + "appears_in_exams": [ + "midterm_2024" + ] + } + ], + "sections": { + "lecture_snippets": [ + { + "id": "ks-65c4de2e9d", + "week": 2, + "source": "materials/lectures/Lecture Week 2.md", + "source_type": "lecture", + "topic": "Dictionaries and Mappings", + "subtopic_id": "w2-dictionaries-and-mappings-core", + "subtopic_title": "Creation, Lookup, Updates, and Key Constraints", + "title": "Dictionaries", + "explanation": "Sets of key:value pairs. Keys must be unique and immutable (hashable). Dictionaries are unordered for equality ({1:1,2:2}=={2:2,1:1} is True). Cannot be sorted. You can check membership with 'in' — this checks KEYS only. Keys() gives key sequence, values() gives value sequence, items() gives tuples.", + "code_examples": [ + { + "description": "Creating and using dicts", + "code": "capitals = {}\ncapitals = dict()\ncapitals = {'Andorra': 'Andorra la Vella', 'Belgium': 'Brussels'}\nprint(capitals['Belgium']) # Brussels\ndel(capitals['Belgium']) # delete key\ncapitals['Netherlands'] = 'Amsterdam' # insert/update\ncapitals.update({'France': 'Paris'}) # insert/update multiple" + }, + { + "description": "Dict membership checks KEYS, not values", + "code": "d = {1: 4, 2: 3}\nprint(1 in d) # True (1 is a key)\nprint(4 in d) # False (4 is a value, not a key)" + }, + { + "description": "Creating dict from two lists", + "code": "l1 = [1, 2, 3, 4]\nl2 = [1, 4, 9, 16]\nsquares = dict(zip(l1, l2))\nprint(squares) # {1:1, 2:4, 3:9, 4:16}" + }, + { + "description": "Dict equality ignores order", + "code": "print({1:1, 2:2} == {2:2, 1:1}) # True\nprint([1,2] == [2,1]) # False" + } + ] + }, + { + "id": "ks-adb6d9f967", + "week": 2, + "source": "materials/lectures/Lecture Week 2.md", + "source_type": "lecture", + "topic": "Dictionaries and Mappings", + "subtopic_id": "w2-dictionaries-and-mappings-core", + "subtopic_title": "Creation, Lookup, Updates, and Key Constraints", + "title": "Looping over dictionaries", + "explanation": ".keys() → key sequence. .values() → value sequence. .items() → sequence of (key, value) tuples. 'for key in dict' is the same as 'for key in dict.keys()'.", + "code_examples": [ + { + "description": "Looping over dict", + "code": "capitals = {'Andorra': 'Andorra la Vella', 'Belgium': 'Brussels'}\nfor key in capitals.keys():\n print(key)\nfor val in capitals.values():\n print(val)\nfor key, value in capitals.items():\n print(key, value)\n# These two are equivalent:\nfor key in capitals:\nfor key in capitals.keys():" + } + ] + } + ], + "exam_questions": [ + { + "id": "exam-trial_midterm-2-w2-dictionaries-and-mappings", + "exam_label": "trial_midterm", + "exam_source": "materials/exams/trial midterm.pdf", + "year": "2024-2025", + "number": 2, + "week": 2, + "topic": "dictionary / dict / key value", + "subtopic_id": "w2-dictionaries-and-mappings-core", + "subtopic_title": "Creation, Lookup, Updates, and Key Constraints", + "question": "Suppose you have a dictionary called characters, of which keys are strings and values are lists of strings.", + "code_context": "characters = {'first' : ['a', 'b', '1', 'c', '5'],\n'second': ['d', '2', 'e', '6', 'f'],\n'third' : ['3', 'g', '7', 'h', 'i']}\nYou want to modify the dictionary such that all the elements in the value lists are only character strings and not numeric\nstrings.\nThe intended output should look like this:\ncharacters = {'first': ['a', 'b', 'c'],\n'second': ['d', 'e', 'f'],\n'third': ['g', 'h', 'i']}\nWhich of the following programs will work as intended?\nHints:\nThe remove() list method removes the first occurrence of the element with the specified value.\nThe isnumeric() string method returns True if all the characters are numeric (0-9), otherwise False.\nA for array in characters.values():\nfor element in array:\nif element.isnumeric():\narray.remove(element)\nB for array in characters.values():\nfor index, element in enumerate(array):\nif element.isnumeric():\ndel array[index]\nC for key, value in characters.items():\nfor element in value:\nif element.isnumeric():\ndel value[value.index(element)]\nD All of the programs will work as intended.", + "options": {}, + "correct": "", + "explanation": "" + }, + { + "id": "exam-trial_midterm-8-w2-dictionaries-and-mappings", + "exam_label": "trial_midterm", + "exam_source": "materials/exams/trial midterm.pdf", + "year": "2024-2025", + "number": 8, + "week": 2, + "topic": "dictionary / dict", + "subtopic_id": "w2-dictionaries-and-mappings-core", + "subtopic_title": "Creation, Lookup, Updates, and Key Constraints", + "question": "Suppose you have the following dictionary:\nlibrary = {\"books\": 5,\n\"genres\": ['action', 'romance', 'thriller', 'classics']}\nYou want to:\n- add a key \"years\", of which the value is a list of strings that are the years of publication, i.e., [\"1932\" , \"2012\", \"1899\",\n\"2000\", \"1984\"],\n- change the value of the key \"books\" to 6.\nThe new value of the dictionary library should be:\n{\"books\" : 6,\n\"genres\" : ['action', 'romance', 'thriller', 'classics'],\n\"years\" : [\"1932\" , \"2012\", \"1899\", \"2000\", \"1984\"]}\nWhich of the programs below will work as intended?\nA library[\"books\"] = 6\nlibrary.update({\"years\": [\"1932\" , \"2012\", \"1899\", \"2000\", \"1984\"]})\nB library[\"books\"] = 6\nlibrary[\"years\"] = [\"1932\" , \"2012\", \"1899\", \"2000\", \"1984\"]\nC Both of the given options\nD None of the given options", + "code_context": "Suppose you have the following dictionary:\nlibrary = {\"books\": 5,\n\"genres\": ['action', 'romance', 'thriller', 'classics']}\nYou want to:\n- add a key \"years\", of which the value is a list of strings that are the years of publication, i.e., [\"1932\" , \"2012\", \"1899\",\n\"2000\", \"1984\"],\n- change the value of the key \"books\" to 6.\nThe new value of the dictionary library should be:\n{\"books\" : 6,\n\"genres\" : ['action', 'romance', 'thriller', 'classics'],\n\"years\" : [\"1932\" , \"2012\", \"1899\", \"2000\", \"1984\"]}\nWhich of the programs below will work as intended?\nA library[\"books\"] = 6\nlibrary.update({\"years\": [\"1932\" , \"2012\", \"1899\", \"2000\", \"1984\"]})\nB library[\"books\"] = 6\nlibrary[\"years\"] = [\"1932\" , \"2012\", \"1899\", \"2000\", \"1984\"]\nC Both of the given options\nD None of the given options", + "options": {}, + "correct": "", + "explanation": "" + }, + { + "id": "exam-trial_midterm-10-w2-dictionaries-and-mappings", + "exam_label": "trial_midterm", + "exam_source": "materials/exams/trial midterm.pdf", + "year": "2024-2025", + "number": 10, + "week": 2, + "topic": "dictionary / dict", + "subtopic_id": "w2-dictionaries-and-mappings-core", + "subtopic_title": "Creation, Lookup, Updates, and Key Constraints", + "question": "Suppose you have the following dictionary:\nx = {1: 10, 2: 20, 3: 30, 4: 40}\nWhat will the following line of code print?\nprint(list(x.values()) + list(x.keys()))\nA This code will result in an error because you cannot concatenate two lists using the + operator.\nB [10, 20, 30, 40, 1, 2, 3, 4]\nC [11, 22, 33, 44]\nD [(1, 10), (2, 20), (3, 30), (4, 40)]", + "code_context": "Suppose you have the following dictionary:\nx = {1: 10, 2: 20, 3: 30, 4: 40}\nWhat will the following line of code print?\nprint(list(x.values()) + list(x.keys()))\nA This code will result in an error because you cannot concatenate two lists using the + operator.\nB [10, 20, 30, 40, 1, 2, 3, 4]\nC [11, 22, 33, 44]\nD [(1, 10), (2, 20), (3, 30), (4, 40)]", + "options": {}, + "correct": "", + "explanation": "" + }, + { + "id": "exam-trial_midterm-19-w2-dictionaries-and-mappings", + "exam_label": "trial_midterm", + "exam_source": "materials/exams/trial midterm.pdf", + "year": "2024-2025", + "number": 19, + "week": 2, + "topic": "dictionary / dict", + "subtopic_id": "w2-dictionaries-and-mappings-core", + "subtopic_title": "Creation, Lookup, Updates, and Key Constraints", + "question": "Suppose you have the following function:\ndef my_count_function(string):\ncounts = {}\nfor letter in string:\nif letter in counts:\ncounts[letter] += 1\nelse:\ncounts[letter] = 1\nreturn counts\nAnd you create the following two dictionaries:\napple_count = my_count_function(\"apple\")\npeach_count = my_count_function(\"peach\")\nWhich of the code snippets of code below prints something different than the other code snippets?\nA print(len(apple_count.keys()))\nB print(len(peach_count.keys()))\nC print(sum(apple_count.values()))\nD print(sum(peach_count.values()))", + "code_context": "Suppose you have the following function:\ndef my_count_function(string):\ncounts = {}\nfor letter in string:\nif letter in counts:\ncounts[letter] += 1\nelse:\ncounts[letter] = 1\nreturn counts\nAnd you create the following two dictionaries:\napple_count = my_count_function(\"apple\")\npeach_count = my_count_function(\"peach\")\nWhich of the code snippets of code below prints something different than the other code snippets?\nA print(len(apple_count.keys()))\nB print(len(peach_count.keys()))\nC print(sum(apple_count.values()))\nD print(sum(peach_count.values()))", + "options": {}, + "correct": "", + "explanation": "" + }, + { + "id": "exam-trial_midterm-23-w2-dictionaries-and-mappings", + "exam_label": "trial_midterm", + "exam_source": "materials/exams/trial midterm.pdf", + "year": "2024-2025", + "number": 23, + "week": 2, + "topic": "dictionary / dict / key value", + "subtopic_id": "w2-dictionaries-and-mappings-core", + "subtopic_title": "Creation, Lookup, Updates, and Key Constraints", + "question": "You have to write a function called summarize which take a list of integers as an argument.", + "code_context": "The function should return a dictionary with the following key-value pairs:\namount: the number of the integers from the input list\nsmallest: the smallest integer from the input list\nlargest: the largest integer from the input list\ntotal: the sum of all integers from the input list\nWhich of the following functions will achieve what you need?\nA def summarize(x):\ny = {}\nx['amount'] = len(y)\nx['smallest'] = min(y)\nx['largest'] = max(y)\nx['total'] = sum(y)\nreturn x\nB def summarize(x):\ny = {}\ntotal = 0\nfor integer in x:\ny['amount'] = len(x)\nif integer == min(x):\ny['smallest'] = min(x)\nelif integer == max(x):\ny['largest'] = max(x)\nelse:\ny['total'] += integer\nreturn y\nC def summarize(x):\ny = {}\nfor integer in x:\nif integer == min(x):\ny['smallest'] == min(x)\nelif integer == max(x):\ny['largest'] == max(x)\nelse:\ny['amount'] == x.count()\ny['total'] == sum(x)\nreturn y\nD None of the functions will work as needed.", + "options": {}, + "correct": "", + "explanation": "" + }, + { + "id": "exam-midterm_2023-5-w2-dictionaries-and-mappings", + "exam_label": "midterm_2023", + "exam_source": "materials/exams/2023.pdf", + "year": "2022-2023", + "number": 5, + "week": 2, + "topic": "dictionary / dict / key value", + "subtopic_id": "w2-dictionaries-and-mappings-core", + "subtopic_title": "Creation, Lookup, Updates, and Key Constraints", + "question": "What is the output of the program below?", + "code_context": "x = {1: 10, 2: 20, 3: 30, 4: 40, 5: 50}\ny = {1: 50, 2: 40, 3: 30, 4: 20, 5: 10}\nz = x.copy()\nfor key, value in x.items():\nif key in y:\nif value <= y[key]:\nz[key] = y[key]\nz[key] = y[key]\nprint(z)\nA {1: 50, 2: 40, 3: 30, 4: 20, 5: 10}\nB {1: 10, 2: 20, 3: 30, 4: 40, 5: 50}\nC None of the given options\nD {}", + "options": {}, + "correct": "", + "explanation": "" + }, + { + "id": "exam-midterm_2023-6-w2-dictionaries-and-mappings", + "exam_label": "midterm_2023", + "exam_source": "materials/exams/2023.pdf", + "year": "2022-2023", + "number": 6, + "week": 2, + "topic": "dictionary / dict", + "subtopic_id": "w2-dictionaries-and-mappings-core", + "subtopic_title": "Creation, Lookup, Updates, and Key Constraints", + "question": "Suppose you have the following dictionary:\nsample_dict = {\n\"name\": \"Kim\",\n\"age\": 25,\n\"birthdate\": \"3-2-1998\",\n\"city\": \"Amsterdam\"}\nSuppose you want to create a dictionary that only contains the keys 'name' and 'city'.\nWhich of the following code snippets return(s) the desired dictionary?\nA keys = [\"name\", \"city\"]\nnew_dict = {}\nfor k in keys:\nnew_dict[k] = sample_dict[k]\nnew_dict\nB keys = [\"age\", \"birthdate\"]\nnew_dict = {}\nnew_keys = sample_dict.keys() - keys\nfor k in new_keys:\nnew_dict[k] = sample_dict[k]\nnew_dict\nC None of the given options\nD Both of the given options", + "code_context": "Suppose you have the following dictionary:\nsample_dict = {\n\"name\": \"Kim\",\n\"age\": 25,\n\"birthdate\": \"3-2-1998\",\n\"city\": \"Amsterdam\"}\nSuppose you want to create a dictionary that only contains the keys 'name' and 'city'.\nWhich of the following code snippets return(s) the desired dictionary?\nA keys = [\"name\", \"city\"]\nnew_dict = {}\nfor k in keys:\nnew_dict[k] = sample_dict[k]\nnew_dict\nB keys = [\"age\", \"birthdate\"]\nnew_dict = {}\nnew_keys = sample_dict.keys() - keys\nfor k in new_keys:\nnew_dict[k] = sample_dict[k]\nnew_dict\nC None of the given options\nD Both of the given options", + "options": {}, "correct": "", "explanation": "" }, @@ -3711,6 +3890,69 @@ }, "correct": "a", "explanation": "Option A is a valid dictionary comprehension that iterates through `words`, setting each `word` as the key and `len(word)` as the value." + }, + { + "id": "exam-intro_python_sample_final_24_25-19-w3-defining-and-calling-functions", + "exam_label": "intro_python_sample_final_24_25", + "exam_source": "materials/post_midterm/Sample Final plus answers.pdf", + "year": "2024", + "number": 19, + "week": 2, + "topic": "Dictionaries", + "subtopic_id": "w2-dictionaries-and-mappings-core", + "subtopic_title": "Creation, Lookup, Updates, and Key Constraints", + "question": "Which of the following programs correctly returns a dictionary where values are sums of input values whose keys are <= the output key?", + "code_context": "main({5: 1, 2: 5, 4: 2}) # Expected: {5: 8, 2: 5, 4: 7}", + "options": { + "A": "A list comprehension based sum in a loop.", + "B": "A running total sum in a sorted key loop.", + "C": "Both of the above work as intended", + "D": "None of the above works as intended" + }, + "correct": "C", + "explanation": "Both methods correctly calculate the cumulative sums based on key values, though Option B is more efficient." + }, + { + "id": "exam-intro_python_sample_final_24_25-20-w3-defining-and-calling-functions", + "exam_label": "intro_python_sample_final_24_25", + "exam_source": "materials/post_midterm/Sample Final plus answers.pdf", + "year": "2024", + "number": 20, + "week": 2, + "topic": "Dictionaries", + "subtopic_id": "w2-dictionaries-and-mappings-core", + "subtopic_title": "Creation, Lookup, Updates, and Key Constraints", + "question": "What is the result of the program comparing d1 (from zip) and d2 (from enumerate)?", + "code_context": "l1 = [1, 2, 3, 4]\nl2 = [2, 3, 4, 5]", + "options": { + "A": "True", + "B": "False", + "C": "An error message.", + "D": "None of the above" + }, + "correct": "A", + "explanation": "Both d1 and d2 result in the same dictionary: {1: 2, 2: 3, 3: 4, 4: 5}." + }, + { + "id": "exam-intro_python_sample_final_24_25-21-w3-defining-and-calling-functions", + "exam_label": "intro_python_sample_final_24_25", + "exam_source": "materials/post_midterm/Sample Final plus answers.pdf", + "year": "2024", + "number": 21, + "week": 2, + "topic": "Dict Iteration", + "subtopic_id": "w2-dictionaries-and-mappings-core", + "subtopic_title": "Creation, Lookup, Updates, and Key Constraints", + "question": "The following codes all print the same value, except one. Which one?", + "code_context": "d1 = {1: 10, 2: 20, 3: 30, 4: 40}", + "options": { + "A": "for key, value in d1: result += value", + "B": "for key in d1.keys(): result += d1[key]", + "C": "for value in d1.values(): result += value", + "D": "result = sum(d1.values())" + }, + "correct": "A", + "explanation": "Iterating directly over a dictionary (for key, value in d1) only yields keys. This will cause a ValueError when trying to unpack into two variables." } ], "notebook_snippets": [ @@ -3817,6 +4059,51 @@ "title": "dictionaries", "source": "capitals = ['Estonia', 'Tallin', 'Belgium', 'Brussels', 'France', 'Paris']\nprint(capitals[capitals.index('Belgium') + 1])\nprint(capitals[capitals.index('Tallin') - 1])", "outputs": [] + }, + { + "id": "cs-curated-hw-dict-digit-frequency", + "week": 2, + "cell_index": null, + "cell_type": "code", + "source_type": "notebook", + "topic": "Dictionaries and Mappings", + "subtopic_id": "w2-dictionaries-and-mappings-core", + "subtopic_title": "Creation, Lookup, Updates, and Key Constraints", + "title": "Count only digit characters that actually appear", + "source": "x = ['1', 'a', 'X', '2', 'b', 'Y', '1', 'a', 'X', '1', 'a', 'X']\ncounts = {}\nfor digit in '0123456789':\n if digit in x:\n counts[digit] = x.count(digit)\nprint(counts)", + "outputs": [ + "{'1': 3, '2': 1}" + ] + }, + { + "id": "cs-curated-hw-dict-delete-shared-keys", + "week": 2, + "cell_index": null, + "cell_type": "code", + "source_type": "notebook", + "topic": "Dictionaries and Mappings", + "subtopic_id": "w2-dictionaries-and-mappings-core", + "subtopic_title": "Creation, Lookup, Updates, and Key Constraints", + "title": "Delete keys only when they also appear in a reference dict", + "source": "x = {'a': 1, 'b': 2, 'c': 3}\nto_remove = {'c': 3, 'd': 3}\nfor key in to_remove:\n if key in x:\n del x[key]\nprint(x)", + "outputs": [ + "{'a': 1, 'b': 2}" + ] + }, + { + "id": "cs-curated-hw-dict-project-values-sorted-keys", + "week": 2, + "cell_index": null, + "cell_type": "code", + "source_type": "notebook", + "topic": "Dictionaries and Mappings", + "subtopic_id": "w2-dictionaries-and-mappings-core", + "subtopic_title": "Creation, Lookup, Updates, and Key Constraints", + "title": "Sort keys first, then project values in that order", + "source": "x = {1: 3, 3: 4, 2: 5}\nsorted_keys = sorted(x.keys(), reverse=True)\nresult = [x[key] for key in sorted_keys]\nprint(result)", + "outputs": [ + "[4, 5, 3]" + ] } ], "ai_summary": { @@ -4028,6 +4315,16 @@ } ], "recommended_ids": [ + "exam-intro_python_sample_final_24_25-19-w3-defining-and-calling-functions", + "exam-intro_python_sample_final_24_25-20-w3-defining-and-calling-functions", + "exam-intro_python_sample_final_24_25-21-w3-defining-and-calling-functions", + "exam-trial-final-exam-py22-4-w2-dictionaries-and-mappings", + "exam-trial-final-exam-py22-5-w2-dictionaries-and-mappings", + "exam-trial-final-exam-py22-6-w2-dictionaries-and-mappings", + "exam-Resit 22/23-7-w2-dictionaries-and-mappings", + "exam-Trial final - Introduction to Python - 22/23-4-w2-dictionaries-and-mappings", + "exam-Trial final - Introduction to Python - 22/23-5-w2-dictionaries-and-mappings", + "exam-Trial final - Introduction to Python - 22/23-6-w2-dictionaries-and-mappings", "exam-trial_midterm-2-w2-dictionaries-and-mappings", "exam-trial_midterm-8-w2-dictionaries-and-mappings", "exam-trial_midterm-10-w2-dictionaries-and-mappings", @@ -4036,6 +4333,42 @@ "ks-adb6d9f967", "cs-f3df72fba8", "cs-38e347e22f" + ], + "homework_snippets": [ + { + "id": "hw-acc93a6860", + "week": 2, + "cell_index": 1, + "cell_type": "code", + "topic": "dictionaries", + "source": "# source: materials/homework/week 2/Exercise_2.1.py\ny = {}\nfor var in '0123456789':\n if var in x:\n y[var]=x.count(var)\nprint(y)\n\n# Alternative Solution:\n\ny = {}\nfor element in x:\n if element in \"0123456789\":\n y[element] = x.count(element)\nprint(y)", + "outputs": [], + "source_origin": "materials/homework/week 2/Exercise_2.1.py" + }, + { + "id": "hw-82ab83e170", + "week": 2, + "cell_index": 3, + "cell_type": "code", + "topic": "dictionaries", + "source": "# source: materials/homework/week 2/Exercise_2.3.py\ny = {'c': 3, 'd': 3}\nfor key, value in y.items():\n if key in x:\n del x[key]\n else:\n x[key] = value", + "outputs": [], + "source_origin": "materials/homework/week 2/Exercise_2.3.py" + }, + { + "id": "hw-9ae0db1eff", + "week": 2, + "cell_index": 6, + "cell_type": "code", + "topic": "dictionaries", + "source": "# source: materials/homework/week 2/Exercise_2.6.py\nsorted_keys = sorted(x.keys(), reverse=True)\n\nresult = []\nfor key in sorted_keys:\n result.append(x[key])\n\nprint(result)", + "outputs": [], + "source_origin": "materials/homework/week 2/Exercise_2.6.py" + } + ], + "homework_recommended_ids": [ + "hw-acc93a6860", + "hw-82ab83e170" ] } }, @@ -4674,6 +5007,10 @@ } ], "recommended_ids": [ + "exam-Resit 22/23-1-w2-lists-and-sets", + "exam-Test Resit - Introduction to Python - 22/23-1-w2-lists-and-sets", + "exam-Test Resit - Introduction to Python - 22/23-5-w2-lists-and-sets", + "exam-trial-final-exam-py22-7-w2-lists-and-sets", "exam-midterm_2023-15-w2-lists-and-sets", "exam-midterm_2023-16-w2-lists-and-sets", "exam-midterm_2024-22-w2-lists-and-sets", @@ -4682,7 +5019,9 @@ "ks-08ac820c2f", "cs-fb52d5602d", "cs-0c13ecd41e" - ] + ], + "homework_snippets": [], + "homework_recommended_ids": [] } }, { @@ -4717,12 +5056,6 @@ "exam-trial_midterm-13-w2-conditions", "exam-midterm_2023-1-w2-conditions", "exam-midterm_2024-2-w2-conditions", - "exam-intro_python_sample_final_24_25-4-w2-conditions", - "exam-intro_python_sample_final_24_25-12-w2-conditions", - "exam-intro_python_sample_final_24_25-15-w2-conditions", - "exam-intro_python_sample_final_24_25-18-w2-conditions", - "exam-intro_python_sample_final_24_25-22-w2-conditions", - "exam-intro_python_sample_final_24_25-24-w2-conditions", "exam-Test Exam 07-06-22-4-w2-conditions" ], "notebook_snippet_ids": [ @@ -4733,7 +5066,8 @@ "cs-45160a5ff6", "cs-ad7786b296", "cs-2e15d5f206", - "cs-932144cfb6" + "cs-932144cfb6", + "cs-curated-hw-conditions-first-match-wins" ], "example_ids": [ "ai-example-1", @@ -4932,163 +5266,37 @@ "correct": "", "explanation": "" }, - { - "id": "exam-midterm_2023-1-w2-conditions", - "exam_label": "midterm_2023", - "exam_source": "materials/exams/2023.pdf", - "year": "2022-2023", - "number": 1, - "week": 2, - "topic": "in", - "subtopic_id": "w2-conditions-core", - "subtopic_title": "Comparisons, `in`, Precedence, and Conditional Expressions", - "question": "What is the output of the following code snippet?", - "code_context": "x = 1\ny = 15\nprint(not(not(x < 3) and not(y > 14 or y > 10)))\nA The code will result in a SyntaxError.\nB True\nC False\nD 0", - "options": {}, - "correct": "", - "explanation": "" - }, - { - "id": "exam-midterm_2024-2-w2-conditions", - "exam_label": "midterm_2024", - "exam_source": "materials/exams/2024.pdf", - "year": "2023-2024", - "number": 2, - "week": 2, - "topic": "in", - "subtopic_id": "w2-conditions-core", - "subtopic_title": "Comparisons, `in`, Precedence, and Conditional Expressions", - "question": "Assume you have the following variables:\nx = 3\ny = 3.0\nz = '3'\nWhat will be printed by the following code:\nprint((x != z and x == int(z)) or (x != y and y != z))\nA True\nB False\nC The code will result in an error.\nD 3", - "code_context": "Assume you have the following variables:\nx = 3\ny = 3.0\nz = '3'\nWhat will be printed by the following code:\nprint((x != z and x == int(z)) or (x != y and y != z))\nA True\nB False\nC The code will result in an error.\nD 3", - "options": {}, - "correct": "", - "explanation": "" - }, - { - "id": "exam-intro_python_sample_final_24_25-4-w2-conditions", - "exam_label": "intro_python_sample_final_24_25", - "exam_source": "materials/post_midterm/Sample Final plus answers.pdf", - "year": "2024", - "number": 4, - "week": 2, - "topic": "String Methods", - "subtopic_id": "w2-conditions-core", - "subtopic_title": "Comparisons, `in`, Precedence, and Conditional Expressions", - "question": "Which of the following code segments does NOT achieve the goal of returning a string with 10 digits by removing dashes?", - "code_context": "", - "options": { - "A": "def format_phone_number(number):\n number.replace(\"-\", \"\")\n return number", - "B": "def format_phone_number(number):\n return number.replace(\"-\", \"\")", - "C": "def format_phone_number(number):\n digits = []\n for char in number:\n if char in \"0123456789\":\n digits.append(char)\n return \"\".join(digits)", - "D": "def format_phone_number(number):\n return \"\".join(number.split(\"-\"))" - }, - "correct": "A", - "explanation": "Strings in Python are immutable. The .replace() method returns a new string but does not modify the original. Option A returns the original string with dashes because the result of .replace() was not assigned back to the variable." - }, - { - "id": "exam-intro_python_sample_final_24_25-12-w2-conditions", - "exam_label": "intro_python_sample_final_24_25", - "exam_source": "materials/post_midterm/Sample Final plus answers.pdf", - "year": "2024", - "number": 12, - "week": 2, - "topic": "List Comprehensions", - "subtopic_id": "w2-conditions-core", - "subtopic_title": "Comparisons, `in`, Precedence, and Conditional Expressions", - "question": "You'd like to turn every upper case letter in a list into lower case and vice versa. Which code line achieves this?", - "code_context": "", - "options": { - "A": "[letter.upper() if letter.islower() else letter.lower() for letter in list_1]", - "B": "[x if x in 'abcdefg...'.upper() else x.lower() for x in list_1]", - "C": "Both achieve what you want", - "D": "None achieves what you want" - }, - "correct": "C", - "explanation": "Both options implement the conditional logic required to flip the case of each character in the list." - }, - { - "id": "exam-intro_python_sample_final_24_25-15-w2-conditions", - "exam_label": "intro_python_sample_final_24_25", - "exam_source": "materials/post_midterm/Sample Final plus answers.pdf", - "year": "2024", - "number": 15, - "week": 2, - "topic": "Functions (Scope)", - "subtopic_id": "w2-conditions-core", - "subtopic_title": "Comparisons, `in`, Precedence, and Conditional Expressions", - "question": "Executing the following program will produce an error. Why?", - "code_context": "def cube(num):\n result = num ** 3\n return f'The cube of {num} is: {result}.'\nprint(result)", - "options": { - "A": "Result is a local name and cannot be referenced outside of the function.", - "B": "** is not a valid Python operator.", - "C": "The syntax of the f-string is incorrect.", - "D": "You can only use either print or return, but not both." - }, - "correct": "A", - "explanation": "The variable 'result' is defined inside the 'cube' function, making it local to that function. It cannot be accessed from the global scope." - }, - { - "id": "exam-intro_python_sample_final_24_25-18-w2-conditions", - "exam_label": "intro_python_sample_final_24_25", - "exam_source": "materials/post_midterm/Sample Final plus answers.pdf", - "year": "2024", - "number": 18, - "week": 2, - "topic": "Slicing", - "subtopic_id": "w2-conditions-core", - "subtopic_title": "Comparisons, `in`, Precedence, and Conditional Expressions", - "question": "How do you break a list into a list of lists, where each sublist contains 3 elements?", - "code_context": "x = ['a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i']", - "options": { - "A": "y = [x[i:(i + 3)] for i in range(0, 7, 3)]", - "B": "y = [x[i[0]::3] for i in enumerate(x)]", - "C": "Both of the above work", - "D": "Neither of above works" - }, - "correct": "A", - "explanation": "Option A uses range(0, 7, 3) which generates 0, 3, 6. The slices x[0:3], x[3:6], and x[6:9] correctly partition the list." - }, - { - "id": "exam-intro_python_sample_final_24_25-22-w2-conditions", - "exam_label": "intro_python_sample_final_24_25", - "exam_source": "materials/post_midterm/Sample Final plus answers.pdf", - "year": "2024", - "number": 22, + { + "id": "exam-midterm_2023-1-w2-conditions", + "exam_label": "midterm_2023", + "exam_source": "materials/exams/2023.pdf", + "year": "2022-2023", + "number": 1, "week": 2, - "topic": "String Methods", + "topic": "in", "subtopic_id": "w2-conditions-core", "subtopic_title": "Comparisons, `in`, Precedence, and Conditional Expressions", - "question": "Which script, using the count string method, would print the value 1 for x = 'Amsterdam'?", - "code_context": "x = 'Amsterdam'", - "options": { - "A": "print(count(x, 'a'))", - "B": "print(x.count('a'))", - "C": "Both scripts would deliver that result", - "D": "Neither script would deliver that result" - }, - "correct": "B", - "explanation": "The count() method is a string method, not a standalone function. It is called using the dot notation on a string object." + "question": "What is the output of the following code snippet?", + "code_context": "x = 1\ny = 15\nprint(not(not(x < 3) and not(y > 14 or y > 10)))\nA The code will result in a SyntaxError.\nB True\nC False\nD 0", + "options": {}, + "correct": "", + "explanation": "" }, { - "id": "exam-intro_python_sample_final_24_25-24-w2-conditions", - "exam_label": "intro_python_sample_final_24_25", - "exam_source": "materials/post_midterm/Sample Final plus answers.pdf", - "year": "2024", - "number": 24, + "id": "exam-midterm_2024-2-w2-conditions", + "exam_label": "midterm_2024", + "exam_source": "materials/exams/2024.pdf", + "year": "2023-2024", + "number": 2, "week": 2, - "topic": "Modules", + "topic": "in", "subtopic_id": "w2-conditions-core", "subtopic_title": "Comparisons, `in`, Precedence, and Conditional Expressions", - "question": "Which script does NOT print the correct answer for the area of a circle?", - "code_context": "", - "options": { - "A": "import math; print(math.pi * r ** 2)", - "B": "from math import pi; print(pi * r ** 2)", - "C": "import math as constants; print(math.pi * r ** 2)", - "D": "from math import pi as constant; print(constant * r ** 2)" - }, - "correct": "C", - "explanation": "If math is imported as constants, it must be referred to as 'constants.pi'. 'math.pi' will no longer be available unless 'math' was also imported directly." + "question": "Assume you have the following variables:\nx = 3\ny = 3.0\nz = '3'\nWhat will be printed by the following code:\nprint((x != z and x == int(z)) or (x != y and y != z))\nA True\nB False\nC The code will result in an error.\nD 3", + "code_context": "Assume you have the following variables:\nx = 3\ny = 3.0\nz = '3'\nWhat will be printed by the following code:\nprint((x != z and x == int(z)) or (x != y and y != z))\nA True\nB False\nC The code will result in an error.\nD 3", + "options": {}, + "correct": "", + "explanation": "" }, { "id": "exam-Test Exam 07-06-22-4-w2-conditions", @@ -5216,6 +5424,21 @@ "title": "conditions", "source": "a = 3\nif a > 1 and a < 5:\n print('a between 2 and 5')", "outputs": [] + }, + { + "id": "cs-curated-hw-conditions-first-match-wins", + "week": 2, + "cell_index": null, + "cell_type": "code", + "source_type": "notebook", + "topic": "Conditions", + "subtopic_id": "w2-conditions-core", + "subtopic_title": "Comparisons, `in`, Precedence, and Conditional Expressions", + "title": "Branch order matters because the first matching condition wins", + "source": "x = [5, 10, 15, 20]\na, b, c, d = 4, 9, 13, 15\nresult = []\nfor element in x:\n if element <= d:\n label = 'cat4'\n elif element >= c:\n label = 'cat3'\n elif element < b:\n label = 'cat2'\n elif element > a:\n label = 'cat1'\n else:\n label = 'catunknown'\n result.append(label)\nprint(result)", + "outputs": [ + "['cat4', 'cat4', 'cat4', 'cat3']" + ] } ], "ai_summary": { @@ -5342,14 +5565,30 @@ } ], "recommended_ids": [ - "exam-trial_midterm-6-w2-conditions", - "exam-trial_midterm-13-w2-conditions", + "exam-Test Exam 07-06-22-4-w2-conditions", "exam-midterm_2023-1-w2-conditions", "exam-midterm_2024-2-w2-conditions", + "exam-trial_midterm-6-w2-conditions", + "exam-trial_midterm-13-w2-conditions", "ks-4b427a2425", "ks-c19999c074", "cs-cc4bdf194b", "cs-a0a4e5c791" + ], + "homework_snippets": [ + { + "id": "hw-a68b2adc08", + "week": 2, + "cell_index": 8, + "cell_type": "code", + "topic": "conditions", + "source": "# source: materials/homework/week 2/Exercise_2.8.py\nresult = []\nfor element in x:\n if element <= d:\n text = \"cat4\"\n elif element >= c:\n text = \"cat3\"\n elif element < b:\n text = \"cat2\"\n elif element > a:\n text = \"cat1\"\n else:\n text = \"catunknown\"\n result.append(text)\n\nprint(result)", + "outputs": [], + "source_origin": "materials/homework/week 2/Exercise_2.8.py" + } + ], + "homework_recommended_ids": [ + "hw-a68b2adc08" ] } }, @@ -5405,14 +5644,19 @@ "cs-24e7b545b8", "cs-29b15eafbc", "cs-37994cff84", - "cs-ab8c33be2c" + "cs-ab8c33be2c", + "cs-curated-hw-loops-enumerate-mark-max", + "cs-curated-hw-loops-zip-filter-pairs", + "cs-curated-hw-loops-market-clearing", + "cs-curated-hw-loops-nested-pairwise-dict" ], "example_ids": [ "ai-example-2", "ai-example-3", "ai-example-4", "ai-example-5", - "ai-example-7" + "ai-example-7", + "manual-loop-max-sublist-sum" ], "key_point_ids": [] } @@ -5849,6 +6093,66 @@ "title": "walrus_operator", "source": "from random import randint\nprint(a := randint(0,5))\nif a > 1 and a < 5:\n print('a between 2 and 5')\nelse: \n print('a not between 2 and 5')", "outputs": [] + }, + { + "id": "cs-curated-hw-loops-enumerate-mark-max", + "week": 2, + "cell_index": null, + "cell_type": "code", + "source_type": "notebook", + "topic": "Loops", + "subtopic_id": "w2-loops-core", + "subtopic_title": "for, while, Dictionary Iteration, enumerate(), zip(), and Walrus", + "title": "Use enumerate() to keep indices while relabeling one special case", + "source": "x = [65, 43, 1, 0, 59, 16, 86, 40, 60]\nmax_value = max(x)\nresult = {}\nfor index, value in enumerate(x):\n key = 'highest' if value == max_value else index\n result[key] = value\nprint(result)", + "outputs": [ + "{0: 65, 1: 43, 2: 1, 3: 0, 4: 59, 5: 16, 'highest': 86, 7: 40, 8: 60}" + ] + }, + { + "id": "cs-curated-hw-loops-zip-filter-pairs", + "week": 2, + "cell_index": null, + "cell_type": "code", + "source_type": "notebook", + "topic": "Loops", + "subtopic_id": "w2-loops-core", + "subtopic_title": "for, while, Dictionary Iteration, enumerate(), zip(), and Walrus", + "title": "zip() aligns two lists so you can filter pairs into a dict", + "source": "keys = [3, 2, 1, 4]\nvalues = [3, 37, 60, 79]\nresult = {}\nfor key, value in zip(keys, values):\n if key != value and value % 5:\n result[key] = value\nprint(result)", + "outputs": [ + "{2: 37, 4: 79}" + ] + }, + { + "id": "cs-curated-hw-loops-market-clearing", + "week": 2, + "cell_index": null, + "cell_type": "code", + "source_type": "notebook", + "topic": "Loops", + "subtopic_id": "w2-loops-core", + "subtopic_title": "for, while, Dictionary Iteration, enumerate(), zip(), and Walrus", + "title": "Flatten, sort, and zip demand/supply curves to count trades", + "source": "buyers = {'buyer1': [24, 16, 13, 6, 5], 'buyer2': [23, 21, 19, 10, 7], 'buyer3': [21, 20, 15, 13, 10], 'buyer4': [20, 17, 9, 6, 5]}\nsellers = {'seller1': [8, 10, 14, 19, 21], 'seller2': [6, 13, 16, 21, 23], 'seller3': [8, 12, 13, 22, 23], 'seller4': [8, 9, 13, 21, 24]}\ndemand = []\nfor buyer_values in buyers.values():\n demand += buyer_values\nsupply = []\nfor seller_values in sellers.values():\n supply += seller_values\nquantity_sold = 0\nfor bid, ask in zip(sorted(demand, reverse=True), sorted(supply)):\n if bid >= ask:\n quantity_sold += 1\nprint(quantity_sold)", + "outputs": [ + "10" + ] + }, + { + "id": "cs-curated-hw-loops-nested-pairwise-dict", + "week": 3, + "cell_index": null, + "cell_type": "code", + "source_type": "notebook", + "topic": "Loops", + "subtopic_id": "w2-loops-core", + "subtopic_title": "for, while, Dictionary Iteration, enumerate(), zip(), and Walrus", + "title": "Nested loops can build pairwise results for every combination", + "source": "def main(minimum, maximum):\n result = {}\n for first in range(minimum, maximum + 1):\n for second in range(minimum, maximum + 1):\n result[(first, second)] = first - second\n return result\n\nprint(main(2, 4))", + "outputs": [ + "{(2, 2): 0, (2, 3): -1, (2, 4): -2, (3, 2): 1, (3, 3): 0, (3, 4): -1, (4, 2): 2, (4, 3): 1, (4, 4): 0}" + ] } ], "ai_summary": { @@ -5968,17 +6272,97 @@ "status": "curated", "subtopic_id": "w2-loops-core", "subtopic_title": "for, while, Dictionary Iteration, enumerate(), zip(), and Walrus" + }, + { + "id": "manual-loop-max-sublist-sum", + "kind": "correct", + "title": "Keep the sub-list whose elements have the largest sum", + "code": "lists = [[1, 2], [4, 4], [3, 3, 1]]\nbest = lists[0]\nfor current in lists[1:]:\n if sum(current) > sum(best):\n best = current\nprint(best)", + "output": "[4, 4]", + "why": "Store the current best sub-list, compare `sum(current)` with `sum(best)` on each iteration, and update the winner when you find a larger total.", + "status": "curated", + "subtopic_id": "w2-loops-core", + "subtopic_title": "for, while, Dictionary Iteration, enumerate(), zip(), and Walrus" } ], "recommended_ids": [ - "exam-trial_midterm-5-w2-loops", + "exam-intro_python_sample_final_24_25-14-w2-loops", + "exam-Test Resit - Introduction to Python - 22/23-4-w2-loops", "exam-midterm_2023-2-w2-loops", - "exam-midterm_2023-14-w2-loops", "exam-midterm_2024-3-w2-loops", + "exam-trial_midterm-5-w2-loops", + "exam-midterm_2023-14-w2-loops", "ks-72c9eada91", "ks-bddafc66a0", "ks-59aaf6b0ee", "ks-4c6274845e" + ], + "homework_snippets": [ + { + "id": "hw-2819f846a5", + "week": 2, + "cell_index": 2, + "cell_type": "code", + "topic": "while_loops", + "source": "# source: materials/homework/week 2/Exercise_2.2.py\nimport math\n\ny = {}\nangle = 0\nwhile angle <= 45:\n angle_in_radians = math.radians(angle)\n y[angle] = round(math.tan(angle_in_radians), 4)\n angle = angle + x", + "outputs": [], + "source_origin": "materials/homework/week 2/Exercise_2.2.py" + }, + { + "id": "hw-bcb4a5a2a8", + "week": 2, + "cell_index": 4, + "cell_type": "code", + "topic": "enumerate", + "source": "# source: materials/homework/week 2/Exercise_2.4.py\ny = {}\nfor key, value in enumerate(x):\n y['highest' if value == max(x) else key]= value", + "outputs": [], + "source_origin": "materials/homework/week 2/Exercise_2.4.py" + }, + { + "id": "hw-1552d61245", + "week": 2, + "cell_index": 5, + "cell_type": "code", + "topic": "zip", + "source": "# source: materials/homework/week 2/Exercise_2.5.py\nx = {}\nfor key, value in zip(keys, values):\n if key != value and value % 5:\n x[key] = value", + "outputs": [], + "source_origin": "materials/homework/week 2/Exercise_2.5.py" + }, + { + "id": "hw-d5812572f6", + "week": 2, + "cell_index": 9, + "cell_type": "code", + "topic": "for_loops", + "source": "# source: materials/homework/week 2/Exercise_2.9.py\ndemand = []\nfor buyer_values in buyers.values():\n demand = demand + buyer_values\ndemand = sorted(demand, reverse=True)\n\nsupply = []\nfor seller_values in sellers.values():\n supply = supply + seller_values\nsupply = sorted(supply, reverse=False)\n\nquantity_sold = 0\nfor buyer_value, supplyer_value in zip(demand, supply):\n quantity_sold += buyer_value >= supplyer_value\n\nprint(quantity_sold)", + "outputs": [], + "source_origin": "materials/homework/week 2/Exercise_2.9.py" + }, + { + "id": "hw-f07fb0c149", + "week": 3, + "cell_index": 1, + "cell_type": "code", + "topic": "nested_loops", + "source": "# source: materials/homework/week 3/Exercise_3.1.py\ndef main(minimum, maximum):\n result = {}\n for first in range(minimum, maximum + 1):\n for second in range(minimum, maximum + 1):\n result[(first, second)] = first - second\n return result", + "outputs": [], + "source_origin": "materials/homework/week 3/Exercise_3.1.py" + }, + { + "id": "hw-4ecff3d996", + "week": 3, + "cell_index": 8, + "cell_type": "code", + "topic": "zip", + "source": "# source: materials/homework/week 3/Exercise_3.8.py\ndef main(list_1, list_2):\n result = []\n for first, second in zip(list_1, list_2):\n result.append(None if first == second else min(first, second))\n return result", + "outputs": [], + "source_origin": "materials/homework/week 3/Exercise_3.8.py" + } + ], + "homework_recommended_ids": [ + "hw-2819f846a5", + "hw-bcb4a5a2a8", + "hw-1552d61245" ] } }, @@ -6346,6 +6730,31 @@ "cs-46fcecf59e", "cs-896f56060f", "cs-a4025bda25" + ], + "homework_snippets": [ + { + "id": "hw-732a093fb6", + "week": 1, + "cell_index": 7, + "cell_type": "code", + "topic": "type_conversion", + "source": "# source: materials/homework/week 1/Exercise_1.6.py\nprint(float(x + '50'))", + "outputs": [], + "source_origin": "materials/homework/week 1/Exercise_1.6.py" + }, + { + "id": "hw-28c25f5569", + "week": 2, + "cell_index": 7, + "cell_type": "code", + "topic": "truthy_falsy", + "source": "# source: materials/homework/week 2/Exercise_2.7.py\nprint(sum(x) % 2 == 0)", + "outputs": [], + "source_origin": "materials/homework/week 2/Exercise_2.7.py" + } + ], + "homework_recommended_ids": [ + "hw-732a093fb6" ] } }, @@ -6382,9 +6791,6 @@ "exam-intro_python_sample_final_24_25-3-w3-defining-and-calling-functions", "exam-intro_python_sample_final_24_25-11-w3-defining-and-calling-functions", "exam-intro_python_sample_final_24_25-17-w3-defining-and-calling-functions", - "exam-intro_python_sample_final_24_25-19-w3-defining-and-calling-functions", - "exam-intro_python_sample_final_24_25-20-w3-defining-and-calling-functions", - "exam-intro_python_sample_final_24_25-21-w3-defining-and-calling-functions", "exam-Trial final exam Introduction to Python-4-w3-defining-and-calling-functions" ], "notebook_snippet_ids": [ @@ -6663,69 +7069,6 @@ "correct": "D", "explanation": "The function checks if all elements in the input list are either all empty or all non-empty. For the sets and lists provided, they are consistent within each call." }, - { - "id": "exam-intro_python_sample_final_24_25-19-w3-defining-and-calling-functions", - "exam_label": "intro_python_sample_final_24_25", - "exam_source": "materials/post_midterm/Sample Final plus answers.pdf", - "year": "2024", - "number": 19, - "week": 3, - "topic": "Dictionaries", - "subtopic_id": "w3-defining-and-calling-functions-core", - "subtopic_title": "def, Calls, and Methods vs Functions", - "question": "Which of the following programs correctly returns a dictionary where values are sums of input values whose keys are <= the output key?", - "code_context": "main({5: 1, 2: 5, 4: 2}) # Expected: {5: 8, 2: 5, 4: 7}", - "options": { - "A": "A list comprehension based sum in a loop.", - "B": "A running total sum in a sorted key loop.", - "C": "Both of the above work as intended", - "D": "None of the above works as intended" - }, - "correct": "C", - "explanation": "Both methods correctly calculate the cumulative sums based on key values, though Option B is more efficient." - }, - { - "id": "exam-intro_python_sample_final_24_25-20-w3-defining-and-calling-functions", - "exam_label": "intro_python_sample_final_24_25", - "exam_source": "materials/post_midterm/Sample Final plus answers.pdf", - "year": "2024", - "number": 20, - "week": 3, - "topic": "Dictionaries", - "subtopic_id": "w3-defining-and-calling-functions-core", - "subtopic_title": "def, Calls, and Methods vs Functions", - "question": "What is the result of the program comparing d1 (from zip) and d2 (from enumerate)?", - "code_context": "l1 = [1, 2, 3, 4]\nl2 = [2, 3, 4, 5]", - "options": { - "A": "True", - "B": "False", - "C": "An error message.", - "D": "None of the above" - }, - "correct": "A", - "explanation": "Both d1 and d2 result in the same dictionary: {1: 2, 2: 3, 3: 4, 4: 5}." - }, - { - "id": "exam-intro_python_sample_final_24_25-21-w3-defining-and-calling-functions", - "exam_label": "intro_python_sample_final_24_25", - "exam_source": "materials/post_midterm/Sample Final plus answers.pdf", - "year": "2024", - "number": 21, - "week": 3, - "topic": "Dict Iteration", - "subtopic_id": "w3-defining-and-calling-functions-core", - "subtopic_title": "def, Calls, and Methods vs Functions", - "question": "The following codes all print the same value, except one. Which one?", - "code_context": "d1 = {1: 10, 2: 20, 3: 30, 4: 40}", - "options": { - "A": "for key, value in d1: result += value", - "B": "for key in d1.keys(): result += d1[key]", - "C": "for value in d1.values(): result += value", - "D": "result = sum(d1.values())" - }, - "correct": "A", - "explanation": "Iterating directly over a dictionary (for key, value in d1) only yields keys. This will cause a ValueError when trying to unpack into two variables." - }, { "id": "exam-Trial final exam Introduction to Python-4-w3-defining-and-calling-functions", "exam_label": "Trial final exam Introduction to Python", @@ -7004,15 +7347,19 @@ } ], "recommended_ids": [ - "exam-Test Exam 07-06-22-3-w3-defining-and-calling-functions", - "exam-Test Exam 07-06-22-4-w3-defining-and-calling-functions", "exam-intro_python_sample_final_24_25-3-w3-defining-and-calling-functions", "exam-intro_python_sample_final_24_25-11-w3-defining-and-calling-functions", + "exam-intro_python_sample_final_24_25-17-w3-defining-and-calling-functions", + "exam-Test Exam 07-06-22-3-w3-defining-and-calling-functions", + "exam-Trial final exam Introduction to Python-4-w3-defining-and-calling-functions", + "exam-Test Exam 07-06-22-4-w3-defining-and-calling-functions", "ks-e09d7f145b", "ks-ab66f3bab6", "cs-024f83faaa", "cs-c6ee2f0b9a" - ] + ], + "homework_snippets": [], + "homework_recommended_ids": [] } }, { @@ -7670,15 +8017,19 @@ } ], "recommended_ids": [ + "exam-trial-final-exam-py22-3-w3-return-behavior", + "exam-Resit 22/23-3-w3-return-behavior", + "exam-Trial final - Introduction to Python - 22/23-3-w3-return-behavior", "exam-midterm_2024-1-w3-return-behavior", "exam-extra_practice-7-w3-return-behavior", "exam-extra_practice-9-w3-return-behavior", - "exam-Trial final - Introduction to Python - 22/23-3-w3-return-behavior", "ks-00b2983ca8", "ks-14515a5856", "ks-d1a2d7739d", "ks-db93da9e3e" - ] + ], + "homework_snippets": [], + "homework_recommended_ids": [] } }, { @@ -7714,7 +8065,8 @@ "exam-Trial final - Introduction to Python - 22/23-2-w3-scope", "exam-trial-final-exam-py22-2-w3-scope", "exam-Test Resit - Introduction to Python - 22/23-2-w3-scope", - "exam-Resit 22/23-2-w3-scope" + "exam-Resit 22/23-2-w3-scope", + "exam-intro_python_sample_final_24_25-15-w2-conditions" ], "notebook_snippet_ids": [ "cs-2768956dff", @@ -7923,19 +8275,40 @@ "year": "2022-2023", "number": 2, "week": 3, - "topic": "1_Basics_Scope_1", + "topic": "1_Basics_Scope_1", + "subtopic_id": "w3-scope-core", + "subtopic_title": "Global vs Local Names and Scope Errors", + "question": "Executing the following program will produce an error. Why?", + "code_context": "def power(num, factor):\n result = num ** factor\n return 'The result of {} ** {} is: {}.'.format(num, factor, result)\nprint(result)", + "options": { + "a": "Result is a local name that cannot be referenced outside of the function power.", + "b": "** is not a valid Python operator.", + "c": "The syntax used in the return statement to format the string is incorrect.", + "d": "The function called power should not return the string 'The result of {} ** {} is: {}.'.format(num, factor, result), but the value of result." + }, + "correct": "a", + "explanation": "The variable `result` is defined inside the `power` function, giving it local scope. It cannot be accessed outside the function in the global scope where `print(result)` is called." + }, + { + "id": "exam-intro_python_sample_final_24_25-15-w2-conditions", + "exam_label": "intro_python_sample_final_24_25", + "exam_source": "materials/post_midterm/Sample Final plus answers.pdf", + "year": "2024", + "number": 15, + "week": 3, + "topic": "Functions (Scope)", "subtopic_id": "w3-scope-core", "subtopic_title": "Global vs Local Names and Scope Errors", "question": "Executing the following program will produce an error. Why?", - "code_context": "def power(num, factor):\n result = num ** factor\n return 'The result of {} ** {} is: {}.'.format(num, factor, result)\nprint(result)", + "code_context": "def cube(num):\n result = num ** 3\n return f'The cube of {num} is: {result}.'\nprint(result)", "options": { - "a": "Result is a local name that cannot be referenced outside of the function power.", - "b": "** is not a valid Python operator.", - "c": "The syntax used in the return statement to format the string is incorrect.", - "d": "The function called power should not return the string 'The result of {} ** {} is: {}.'.format(num, factor, result), but the value of result." + "A": "Result is a local name and cannot be referenced outside of the function.", + "B": "** is not a valid Python operator.", + "C": "The syntax of the f-string is incorrect.", + "D": "You can only use either print or return, but not both." }, - "correct": "a", - "explanation": "The variable `result` is defined inside the `power` function, giving it local scope. It cannot be accessed outside the function in the global scope where `print(result)` is called." + "correct": "A", + "explanation": "The variable 'result' is defined inside the 'cube' function, making it local to that function. It cannot be accessed from the global scope." } ], "notebook_snippets": [ @@ -8136,15 +8509,21 @@ } ], "recommended_ids": [ + "exam-intro_python_sample_final_24_25-15-w2-conditions", + "exam-trial-final-exam-py22-2-w3-scope", + "exam-Resit 22/23-2-w3-scope", + "exam-Test Resit - Introduction to Python - 22/23-2-w3-scope", + "exam-Trial final - Introduction to Python - 22/23-2-w3-scope", + "exam-extra_practice-2-w3-scope", "exam-midterm_2023-3-w3-scope", "exam-midterm_2024-5-w3-scope", - "exam-extra_practice-2-w3-scope", - "exam-Trial final - Introduction to Python - 22/23-2-w3-scope", "ks-2a6510492d", "cs-2768956dff", "cs-f037678ad8", "cs-3426218e9e" - ] + ], + "homework_snippets": [], + "homework_recommended_ids": [] } }, { @@ -8823,6 +9202,10 @@ } ], "recommended_ids": [ + "exam-intro_python_sample_final_24_25-23-w3-arguments", + "exam-Resit 22/23-4-w3-arguments", + "exam-Test Resit - Introduction to Python - 22/23-6-w3-arguments", + "exam-Resit 22/23-6-w3-arguments", "exam-midterm_2023-9-w3-arguments", "exam-midterm_2023-10-w3-arguments", "exam-midterm_2024-13-w3-arguments", @@ -8831,6 +9214,63 @@ "ks-f5d65c7e89", "ks-d26b85265c", "cs-8276f5c924" + ], + "homework_snippets": [ + { + "id": "hw-bee347cb65", + "week": 3, + "cell_index": 2, + "cell_type": "code", + "topic": "keyword_args", + "source": "# source: materials/homework/week 3/Exercise_3.2.py\ndef main(**kwargs):\n x = {}\n for key, value in kwargs.items():\n x[key] = int(value % 5)\n return x", + "outputs": [], + "source_origin": "materials/homework/week 3/Exercise_3.2.py" + }, + { + "id": "hw-805a1f9f76", + "week": 3, + "cell_index": 3, + "cell_type": "code", + "topic": "args_star", + "source": "# source: materials/homework/week 3/Exercise_3.3.py\ndef main(*args, allowed_value=16):\n x = {}\n for arg in args:\n for key, value in arg.items():\n if value == allowed_value:\n x[key] = value\n return x", + "outputs": [], + "source_origin": "materials/homework/week 3/Exercise_3.3.py" + }, + { + "id": "hw-7949d0413c", + "week": 3, + "cell_index": 4, + "cell_type": "code", + "topic": "default_args", + "source": "# source: materials/homework/week 3/Exercise_3.4.py\ndef main(value_list, excluded_type=int):\n x = []\n for item in value_list:\n if type(item) != excluded_type:\n x.append(item)\n return x", + "outputs": [], + "source_origin": "materials/homework/week 3/Exercise_3.4.py" + }, + { + "id": "hw-711ac9cafc", + "week": 3, + "cell_index": 5, + "cell_type": "code", + "topic": "args_star", + "source": "# source: materials/homework/week 3/Exercise_3.5.py\ndef main(*args):\n x = {}\n for key in args:\n y = []\n for number in args:\n if number < key and key % number == 0:\n y.append(number)\n x[key] = sorted(y, reverse=True)\n return x", + "outputs": [], + "source_origin": "materials/homework/week 3/Exercise_3.5.py" + }, + { + "id": "hw-93552e58b9", + "week": 3, + "cell_index": 7, + "cell_type": "code", + "topic": "default_args", + "source": "# source: materials/homework/week 3/Exercise_3.7.py\ndef main(symbols, winning_symbol=\"*\"):\n pattern = 2 * (winning_symbol + \" \") + winning_symbol\n match = winning_symbol + \"-BINGO!!!\"\n no_match = \"--\"\n return match if symbols == pattern else no_match", + "outputs": [], + "source_origin": "materials/homework/week 3/Exercise_3.7.py" + } + ], + "homework_recommended_ids": [ + "hw-bee347cb65", + "hw-805a1f9f76", + "hw-7949d0413c" ] } }, @@ -8878,7 +9318,8 @@ "cs-b6925be20a", "cs-ab85cbecac", "cs-1b7f6fe8ff", - "cs-14cb7aace2" + "cs-14cb7aace2", + "cs-curated-hw-hof-nested-helper-hhi" ], "example_ids": [ "ai-example-1", @@ -9202,6 +9643,21 @@ "title": "sorted_key", "source": "l1 = ['ad', 'dc', 'ce']\nprint(sorted(l1, key=lambda x: x[1]))", "outputs": [] + }, + { + "id": "cs-curated-hw-hof-nested-helper-hhi", + "week": 3, + "cell_index": null, + "cell_type": "code", + "source_type": "notebook", + "topic": "Higher-Order Patterns", + "subtopic_id": "w3-higher-order-patterns-core", + "subtopic_title": "Nested Functions, Factories, lambda, map, filter, reduce, and sorted(key=...)", + "title": "A nested helper can hide repeated domain math inside one outer function", + "source": "def main(sales_before_entry):\n def calculate_hhi(sales_volumes):\n total_sales = sum(sales_volumes)\n return sum(round(100 * volume / total_sales) ** 2 for volume in sales_volumes)\n\n before = calculate_hhi(sales_before_entry)\n after = calculate_hhi(sales_before_entry + [40])\n return before - after\n\nprint(main([47, 21, 27, 29, 11, 6, 18]))", + "outputs": [ + "224" + ] } ], "ai_summary": { @@ -9435,14 +9891,40 @@ } ], "recommended_ids": [ - "exam-trial_midterm-17-w3-higher-order-patterns", + "exam-intro_python_sample_final_24_25-16-w3-higher-order-patterns", "exam-midterm_2023-11-w3-higher-order-patterns", "exam-midterm_2023-13-w3-higher-order-patterns", + "exam-trial_midterm-17-w3-higher-order-patterns", "exam-midterm_2024-19-w3-higher-order-patterns", "ks-f069ee6a0b", "ks-58858d6d96", "ks-994a4083e3", "cs-a4a5a57502" + ], + "homework_snippets": [ + { + "id": "hw-1f95c6dbd7", + "week": 3, + "cell_index": 6, + "cell_type": "code", + "topic": "function_factories", + "source": "# source: materials/homework/week 3/Exercise_3.6.py\ndef main(sales_before_entry):\n def calculate_hhi(sales_volumes):\n total_sales = sum(sales_volumes)\n hhi = 0\n for volume in sales_volumes:\n hhi += round(100 * volume / total_sales)**2\n return hhi\n\n hhi_before_entry = calculate_hhi(sales_before_entry)\n hhi_after_entry = calculate_hhi(sales_before_entry + [40])\n\n return hhi_before_entry - hhi_after_entry", + "outputs": [], + "source_origin": "materials/homework/week 3/Exercise_3.6.py" + }, + { + "id": "hw-1a9c819007", + "week": 3, + "cell_index": 9, + "cell_type": "code", + "topic": "lambda", + "source": "# source: materials/homework/week 3/Exercise_3.9.py\nprint(sum(map(lambda x: 5 * x + 6, integer_list)))", + "outputs": [], + "source_origin": "materials/homework/week 3/Exercise_3.9.py" + } + ], + "homework_recommended_ids": [ + "hw-1f95c6dbd7" ] } }, @@ -9473,11 +9955,7 @@ "ks-b734a22f46", "ks-309158a68c" ], - "exam_question_ids": [ - "exam-intro_python_sample_final_24_25-5-w4-string-fundamentals", - "exam-intro_python_sample_final_24_25-7-w4-string-fundamentals", - "exam-intro_python_sample_final_24_25-8-w4-string-fundamentals" - ], + "exam_question_ids": [], "notebook_snippet_ids": [ "cs-e7bc165499", "cs-14245b8c1f", @@ -9641,71 +10119,7 @@ ] } ], - "exam_questions": [ - { - "id": "exam-intro_python_sample_final_24_25-5-w4-string-fundamentals", - "exam_label": "intro_python_sample_final_24_25", - "exam_source": "materials/post_midterm/Sample Final plus answers.pdf", - "year": "2024", - "number": 5, - "week": 4, - "topic": "Pandas (Basic)", - "subtopic_id": "w4-string-fundamentals-core", - "subtopic_title": "Quotes, Escape Characters, and Immutability", - "question": "You have a pandas DataFrame called df with columns \"A\" and \"B\". You'd like to create a column called \"C\", which contains the sum of the numbers in columns \"A\" and \"B\". Which of the following code lines will achieve what you want?", - "code_context": "", - "options": { - "A": "df.loc[:,\"C\"] = df.loc[:,\"A\"] + df.loc[:,\"B\"]", - "B": "df.loc[\"c\"] = df.loc[\"A\"] + df.loc[\"B\"]", - "C": "df.loc[\"C\"] = df.loc[:,(\"A\" + \"B\")]", - "D": "df.loc[\"C\"] = df.loc[\"A\" + \"B\"]" - }, - "correct": "A", - "explanation": "Vectorized addition in Pandas is performed by adding series together. Using .loc[:, 'C'] correctly assigns the result to a new column for all rows." - }, - { - "id": "exam-intro_python_sample_final_24_25-7-w4-string-fundamentals", - "exam_label": "intro_python_sample_final_24_25", - "exam_source": "materials/post_midterm/Sample Final plus answers.pdf", - "year": "2024", - "number": 7, - "week": 4, - "topic": "Pandas (Subset/Sort)", - "subtopic_id": "w4-string-fundamentals-core", - "subtopic_title": "Quotes, Escape Characters, and Immutability", - "question": "Which of the following code lines could NOT have created df2 from df1?", - "code_context": "", - "options": { - "A": "df2 = df1.sort_index(ascending=False).loc[:,[\"A\", \"C\", \"D\"]]", - "B": "df2 = df1.iloc[[3, 2, 1], [0, 2, 3]]", - "C": "df2 = df1.loc[2:4, [\"A\", \"C\", \"D\"]].sort_values(\"D\", ascending=False)", - "D": "df2 = df1.loc[2:4, [\"A\", \"C\", \"D\"]].sort_values(\"C\")" - }, - "correct": "A", - "explanation": "Option A would sort all 5 rows of df1 and keep columns A, C, D, resulting in a 5-row DataFrame. df2 only has 3 rows (indices 4, 3, 2)." - }, - { - "id": "exam-intro_python_sample_final_24_25-8-w4-string-fundamentals", - "exam_label": "intro_python_sample_final_24_25", - "exam_source": "materials/post_midterm/Sample Final plus answers.pdf", - "year": "2024", - "number": 8, - "week": 4, - "topic": "Pandas (Series Strings)", - "subtopic_id": "w4-string-fundamentals-core", - "subtopic_title": "Quotes, Escape Characters, and Immutability", - "question": "You have a Series s with municipality and province names separated by \"; \". You'd like to create a new Series that only contains the municipality names. Which of the following code lines will achieve what you want?", - "code_context": "", - "options": { - "A": "s.map(lambda x: x.split(\"; \")[0])", - "B": "s.split(\"; \")[0]", - "C": "s.lambda(x.split(\"; \"))", - "D": "s.str[:9]" - }, - "correct": "A", - "explanation": "The .map() method allows applying a function (like splitting a string and taking the first part) to every element in a pandas Series." - } - ], + "exam_questions": [], "notebook_snippets": [ { "id": "cs-e7bc165499", @@ -10025,84 +10439,18 @@ } ], "recommended_ids": [ - "exam-intro_python_sample_final_24_25-5-w4-string-fundamentals", - "exam-intro_python_sample_final_24_25-7-w4-string-fundamentals", - "exam-intro_python_sample_final_24_25-8-w4-string-fundamentals", "ks-b734a22f46", "ks-309158a68c", "cs-e7bc165499", "cs-14245b8c1f", "cs-9100281cb9" - ] + ], + "homework_snippets": [], + "homework_recommended_ids": [] } }, { - "id": "w4-string-operations-and-methods", - "topic": "String Operations and Methods", "canonical_topic": "w4-string-operations-and-methods", - "weeks": [ - 4 - ], - "week_id": "week-4", - "topic_meta": { - "week": 4, - "week_id": "week-4", - "week_title": "Week 4", - "topic_id": "w4-string-operations-and-methods", - "topic_title": "String Operations and Methods", - "topic_order": 2 - }, - "subtopics": [ - { - "id": "w4-string-operations-and-methods-core", - "title": "Slicing with Step, Search, replace, join, strip, and the string Module", - "order": 1, - "summary": "Trace string slicing, search, replacement, splitting, joining, and stripping. Compare `.find` versus `.index`, and remember `join` is called on the separator.", - "item_ids": { - "lecture_snippet_ids": [ - "ks-5198d93ec1", - "ks-f80f1bf556", - "ks-cdb152720e", - "ks-45aead894c", - "ks-bdea67862f", - "ks-e4dc502d3e" - ], - "exam_question_ids": [ - "exam-intro_python_sample_final_24_25-6-w4-string-operations-and-methods" - ], - "notebook_snippet_ids": [ - "cs-1c6788a4b3", - "cs-399e4a20ca", - "cs-fe295c3cf2", - "cs-c9b5098b60", - "cs-7956253888", - "cs-bccefd5e48", - "cs-be799f0dcb", - "cs-3267796c45" - ], - "example_ids": [ - "ai-example-1", - "ai-example-2", - "ai-example-3", - "ai-example-4", - "ai-example-5", - "ai-example-6", - "ai-example-7", - "ai-example-8" - ], - "key_point_ids": [ - "kp-1", - "kp-2", - "kp-3", - "kp-4", - "kp-5", - "kp-6", - "kp-7", - "kp-manual-string-method-results" - ] - } - } - ], "exam_stats": { "total_hits": 1, "by_exam": { @@ -10110,278 +10458,177 @@ }, "coverage_count": 1 }, + "id": "w4-string-operations-and-methods", "related_topics": [ "Slicing with Step, Search, replace, join, strip, and the string Module" ], - "trap_patterns": [ - { - "pattern": "Slicing creates a NEW object", - "trap": "l2=l1 vs l2=l1[:] — l2=l1 shares the SAME object, slicing creates independent copy", - "weeks": [ - 1 + "sections": { + "ai_common_questions": { + "status": "curated", + "bullets": [ + "Suppose that you'd like to create a new DataFrame that contains only column 'B' for rows with indices 2, 4, and 6. Which of the following code lines will achieve what you want?", + "l2=l1 vs l2=l1[:] — l2=l1 shares the SAME object, slicing creates independent copy", + "range(1,10,3)→[1,4,7] not including 10; l[2:7] goes up to but not including index 7", + "l[::-2] starts from last element going backwards with step 2. l[::2][::-1] first takes every other starting from 0, then reverses — different result" ], - "appears_in_exams": [ - "trial_midterm", - "midterm_2023", - "midterm_2024", - "extra_practice" - ] - }, - { - "pattern": "range() and slicing both exclusive at stop", - "trap": "range(1,10,3)→[1,4,7] not including 10; l[2:7] goes up to but not including index 7", - "weeks": [ - 1, - 2 + "items": [ + { + "id": "aiq-2", + "summary": "What does the slice s[::-2] do for the string s = 'abcdef'?", + "detail": "The step -2 reverses the string and skips every second character, starting from the end ('f', then 'd', then 'b').", + "extra": "String Slicing", + "subtopic_id": "w4-string-operations-and-methods-core", + "subtopic_title": "Slicing with Step, Search, replace, join, strip, and the string Module" + }, + { + "id": "aiq-5", + "summary": "Slicing creates a NEW object", + "detail": "l2=l1 vs l2=l1[:] — l2=l1 shares the SAME object, slicing creates independent copy", + "extra": "", + "subtopic_id": "", + "subtopic_title": "" + }, + { + "id": "aiq-6", + "summary": "range() and slicing both exclusive at stop", + "detail": "range(1,10,3)→[1,4,7] not including 10; l[2:7] goes up to but not including index 7", + "extra": "", + "subtopic_id": "", + "subtopic_title": "" + }, + { + "id": "manual-find-vs-index", + "summary": "What is the difference between `s.find(x)` and `s.index(x)` when `x` is missing?", + "detail": "`find` returns `-1`; `index` raises `ValueError`.", + "extra": "", + "code": "s = 'banana'\nprint(s.find('x'))\nprint(s.index('x')) # ValueError", + "table": null + } ], - "appears_in_exams": [ - "trial_midterm", - "extra_practice" - ] + "generator": "lecture-first-build", + "model": null }, - { - "pattern": "Negative slicing with step=-2", - "trap": "l[::-2] starts from last element going backwards with step 2. l[::2][::-1] first takes every other starting from 0, then reverses — different result", - "weeks": [ - 1 - ], - "appears_in_exams": [ - "extra_practice" - ] - } - ], - "sections": { - "lecture_snippets": [ + "ai_examples": [ { - "id": "ks-5198d93ec1", - "week": 4, - "source": "materials/post_midterm/Lecture Week 4.pptx", - "source_type": "lecture", - "topic": "String Operations and Methods", + "id": "ai-example-1", + "kind": "correct", + "title": "Behavior when substring is missing", + "code": "s = 'abc'\nprint(s.find('z')) # -1\n# print(s.index('z')) # Raises ValueError", + "why": "Both find() and index() search for a substring. The key difference is that find() returns -1 if the substring is not found, while index() raises a ValueError.", + "output": "", + "status": "curated", "subtopic_id": "w4-string-operations-and-methods-core", - "subtopic_title": "Slicing with Step, Search, replace, join, strip, and the string Module", - "title": "String Searching: find vs index", - "explanation": "Both find() and index() search for a substring. The key difference is that find() returns -1 if the substring is not found, while index() raises a ValueError.", - "code_examples": [ - { - "description": "Behavior when substring is missing", - "code": "s = 'abc'\nprint(s.find('z')) # -1\n# print(s.index('z')) # Raises ValueError" - } - ] + "subtopic_title": "Slicing with Step, Search, replace, join, strip, and the string Module" }, { - "id": "ks-f80f1bf556", - "week": 4, - "source": "materials/post_midterm/Lecture Week 4.pptx", - "source_type": "lecture", - "topic": "String Operations and Methods", + "id": "ai-example-2", + "kind": "correct", + "title": "Slicing examples", + "code": "s = '01234567'\nprint(s[::4]) # '04'\nprint(s[::-2]) # '7531'", + "why": "Slicing allows a third parameter 'step'. s[::2] takes every second character, while s[::-1] reverses the string.", + "output": "", + "status": "curated", "subtopic_id": "w4-string-operations-and-methods-core", - "subtopic_title": "Slicing with Step, Search, replace, join, strip, and the string Module", - "title": "String Slicing with Step", - "explanation": "Slicing allows a third parameter 'step'. s[::2] takes every second character, while s[::-1] reverses the string.", - "code_examples": [ - { - "description": "Slicing examples", - "code": "s = '01234567'\nprint(s[::4]) # '04'\nprint(s[::-2]) # '7531'" - } - ] + "subtopic_title": "Slicing with Step, Search, replace, join, strip, and the string Module" }, { - "id": "ks-cdb152720e", - "week": 4, - "source": "materials/post_midterm/Lecture Week 4.pptx", - "source_type": "lecture", - "topic": "String Operations and Methods", + "id": "ai-example-3", + "kind": "correct", + "title": "Joining a list into a string", + "code": "words = ['a', 'b', 'c']\nprint('-'.join(words)) # 'a-b-c'\nprint(''.join(words)) # 'abc'", + "why": "The join() method takes an iterable (like a list) and concatenates its elements using the string it is called on as a separator.", + "output": "", + "status": "curated", "subtopic_id": "w4-string-operations-and-methods-core", - "subtopic_title": "Slicing with Step, Search, replace, join, strip, and the string Module", - "title": "The join Method", - "explanation": "The join() method takes an iterable (like a list) and concatenates its elements using the string it is called on as a separator.", - "code_examples": [ - { - "description": "Joining a list into a string", - "code": "words = ['a', 'b', 'c']\nprint('-'.join(words)) # 'a-b-c'\nprint(''.join(words)) # 'abc'" - } - ] + "subtopic_title": "Slicing with Step, Search, replace, join, strip, and the string Module" }, { - "id": "ks-45aead894c", - "week": 4, - "source": "materials/post_midterm/Lecture Week 4.pptx", - "source_type": "lecture", - "topic": "String Operations and Methods", + "id": "ai-example-4", + "kind": "correct", + "title": "Limiting replacements", + "code": "s = 'aaaa'\nprint(s.replace('a', 'b', 2)) # 'bbaa'", + "why": "Replaces occurrences of a substring. It accepts an optional 'count' argument to limit the number of replacements.", + "output": "", + "status": "curated", "subtopic_id": "w4-string-operations-and-methods-core", - "subtopic_title": "Slicing with Step, Search, replace, join, strip, and the string Module", - "title": "The replace Method", - "explanation": "Replaces occurrences of a substring. It accepts an optional 'count' argument to limit the number of replacements.", - "code_examples": [ - { - "description": "Limiting replacements", - "code": "s = 'aaaa'\nprint(s.replace('a', 'b', 2)) # 'bbaa'" - } - ] + "subtopic_title": "Slicing with Step, Search, replace, join, strip, and the string Module" }, { - "id": "ks-bdea67862f", - "week": 4, - "source": "materials/post_midterm/Lecture Week 4.pptx", - "source_type": "lecture", - "topic": "String Operations and Methods", + "id": "ai-example-5", + "kind": "correct", + "title": "Importing string constants", + "code": "import string\nprint(string.ascii_lowercase) # 'abcdef...'\nprint(string.digits) # '0123456789'", + "why": "The 'string' module provides pre-defined constants like all lowercase letters, digits, and punctuation.", + "output": "", + "status": "curated", "subtopic_id": "w4-string-operations-and-methods-core", - "subtopic_title": "Slicing with Step, Search, replace, join, strip, and the string Module", - "title": "The string Module", - "explanation": "The 'string' module provides pre-defined constants like all lowercase letters, digits, and punctuation.", - "code_examples": [ - { - "description": "Importing string constants", - "code": "import string\nprint(string.ascii_lowercase) # 'abcdef...'\nprint(string.digits) # '0123456789'" - } - ] + "subtopic_title": "Slicing with Step, Search, replace, join, strip, and the string Module" }, { - "id": "ks-e4dc502d3e", - "week": 4, - "source": "materials/post_midterm/Lecture Week 4.pptx", - "source_type": "lecture", - "topic": "String Operations and Methods", - "subtopic_id": "w4-string-operations-and-methods-core", - "subtopic_title": "Slicing with Step, Search, replace, join, strip, and the string Module", - "title": "String Stripping", - "explanation": "strip() removes leading and trailing characters. lstrip() and rstrip() target the left and right sides respectively.", - "code_examples": [ - { - "description": "Stripping whitespace and characters", - "code": "s = ' abc '\nprint(s.strip()) # 'abc'\ns2 = 'eeabcdee'\nprint(s2.strip('e')) # 'abcd'" - } - ] - } - ], - "exam_questions": [ - { - "id": "exam-intro_python_sample_final_24_25-6-w4-string-operations-and-methods", - "exam_label": "intro_python_sample_final_24_25", - "exam_source": "materials/post_midterm/Sample Final plus answers.pdf", - "year": "2024", - "number": 6, - "week": 4, - "topic": "Pandas (Indexing)", - "subtopic_id": "w4-string-operations-and-methods-core", - "subtopic_title": "Slicing with Step, Search, replace, join, strip, and the string Module", - "question": "Suppose that you'd like to create a new DataFrame that contains only column 'B' for rows with indices 2, 4, and 6. Which of the following code lines will achieve what you want?", - "code_context": "", - "options": { - "A": "df.loc[df.index % 2 == 0, [\"B\"]]", - "B": "df[2, 4, 6, \"B\"]", - "C": "df.iloc[[2, 4, 6], 2]", - "D": "df.loc[2::2, \"B\"]" - }, - "correct": "A", - "explanation": "Option A uses a boolean mask on the index to find even numbers and specifies ['B'] as a list to return a DataFrame. Option D would return a Series." - } - ], - "notebook_snippets": [ - { - "id": "cs-1c6788a4b3", - "week": 4, - "cell_index": null, - "cell_type": "code", - "source_type": "notebook", - "topic": "String Operations and Methods", + "id": "ai-example-6", + "kind": "correct", + "title": "Stripping whitespace and characters", + "code": "s = ' abc '\nprint(s.strip()) # 'abc'\ns2 = 'eeabcdee'\nprint(s2.strip('e')) # 'abcd'", + "why": "strip() removes leading and trailing characters. lstrip() and rstrip() target the left and right sides respectively.", + "output": "", + "status": "curated", "subtopic_id": "w4-string-operations-and-methods-core", - "subtopic_title": "Slicing with Step, Search, replace, join, strip, and the string Module", - "title": "s1 = 'abcdefghabcdefgh'", - "source": "s1 = 'abcdefghabcdefgh'\nprint(s1.find('i'))\nprint(s1[s1.find('i')])\nprint(s1.index('i'))", - "outputs": [] + "subtopic_title": "Slicing with Step, Search, replace, join, strip, and the string Module" }, { - "id": "cs-399e4a20ca", - "week": 4, - "cell_index": null, - "cell_type": "code", - "source_type": "notebook", - "topic": "String Operations and Methods", - "subtopic_id": "w4-string-operations-and-methods-core", - "subtopic_title": "Slicing with Step, Search, replace, join, strip, and the string Module", + "id": "ai-example-7", + "kind": "correct", "title": "s1 = 'abcdefghabcdefgh'", - "source": "s1 = 'abcdefghabcdefgh'\nprint(s1.find('e'))\nprint(s1.index('e', 5))\nprint(s1.find('e', 5, 10))\nprint(s1.index('e', 5, 13))\nprint(s1.find('ef'))\nprint(s1.index('q'))", - "outputs": [] - }, - { - "id": "cs-fe295c3cf2", - "week": 4, - "cell_index": null, - "cell_type": "code", - "source_type": "notebook", - "topic": "String Operations and Methods", - "subtopic_id": "w4-string-operations-and-methods-core", - "subtopic_title": "Slicing with Step, Search, replace, join, strip, and the string Module", - "title": "s1 = 'abcdabcdabcd'", - "source": "s1 = 'abcdabcdabcd'\nprint(s1.replace('a', 'xx'))\nprint(s1.replace('ab', 'xx', 1))\nprint(s1.replace('abc', 'xx', 2))\nprint(s1.replace('abcd', 'xx', 10))\nprint(s1.replace('a', ''))\nprint(s1.replace('q', 'qq'))", - "outputs": [] - }, - { - "id": "cs-c9b5098b60", - "week": 4, - "cell_index": null, - "cell_type": "code", - "source_type": "notebook", - "topic": "String Operations and Methods", - "subtopic_id": "w4-string-operations-and-methods-core", - "subtopic_title": "Slicing with Step, Search, replace, join, strip, and the string Module", - "title": "print('abacad'.index('ac'))", - "source": "print('abacad'.index('ac'))", - "outputs": [] - }, - { - "id": "cs-7956253888", - "week": 4, - "cell_index": null, - "cell_type": "code", - "source_type": "notebook", - "topic": "String Operations and Methods", + "code": "s1 = 'abcdefghabcdefgh'\nprint(s1.find('i'))\nprint(s1[s1.find('i')])\nprint(s1.index('i'))", + "why": "", + "output": "", + "status": "curated", "subtopic_id": "w4-string-operations-and-methods-core", - "subtopic_title": "Slicing with Step, Search, replace, join, strip, and the string Module", - "title": "print(str.index('abacad', 'ac'))", - "source": "print(str.index('abacad', 'ac'))", - "outputs": [] + "subtopic_title": "Slicing with Step, Search, replace, join, strip, and the string Module" }, { - "id": "cs-bccefd5e48", - "week": 4, - "cell_index": null, - "cell_type": "code", - "source_type": "notebook", - "topic": "String Operations and Methods", + "id": "ai-example-8", + "kind": "correct", + "title": "s1 = 'abcdefghabcdefgh'", + "code": "s1 = 'abcdefghabcdefgh'\nprint(s1.find('e'))\nprint(s1.index('e', 5))\nprint(s1.find('e', 5, 10))\nprint(s1.index('e', 5, 13))\nprint(s1.find('ef'))\nprint(s1.index('q'))", + "why": "", + "output": "", + "status": "curated", "subtopic_id": "w4-string-operations-and-methods-core", - "subtopic_title": "Slicing with Step, Search, replace, join, strip, and the string Module", - "title": "l1 = ['abc', 'de', 'fg', 'h']", - "source": "l1 = ['abc', 'de', 'fg', 'h']\nprint('xy'.join(l1))\nprint(''.join(l1))", - "outputs": [] + "subtopic_title": "Slicing with Step, Search, replace, join, strip, and the string Module" }, { - "id": "cs-be799f0dcb", - "week": 4, - "cell_index": null, - "cell_type": "code", - "source_type": "notebook", - "topic": "String Operations and Methods", + "id": "manual-string-format-method", + "kind": "correct", + "title": "Build strings with `.format(...)`", + "code": "template = \"{} scored {} points\"\nprint(template.format(\"Ada\", 9))", + "output": "Ada scored 9 points", + "why": "Use `.format(...)` on the template string, and remember it returns a new string instead of changing the original text in place.", + "status": "curated", "subtopic_id": "w4-string-operations-and-methods-core", - "subtopic_title": "Slicing with Step, Search, replace, join, strip, and the string Module", - "title": "a =sorted('0123456789', key=lambda x: str(int(x) % 2 == 1) + x)", - "source": "a =sorted('0123456789', key=lambda x: str(int(x) % 2 == 1) + x)\nprint(''.join(a))", - "outputs": [] + "subtopic_title": "Slicing with Step, Search, replace, join, strip, and the string Module" }, { - "id": "cs-3267796c45", - "week": 4, - "cell_index": null, - "cell_type": "code", - "source_type": "notebook", - "topic": "String Operations and Methods", + "id": "manual-string-islower-method", + "kind": "correct", + "title": "Check lowercase letters with `.islower()`", + "code": "print(\"amsterdam\".islower())\nprint(\"Amsterdam\".islower())\nprint(\"123\".islower())", + "output": "True\nFalse\nFalse", + "why": "`.islower()` only returns `True` when the string contains at least one cased character and all cased characters are lowercase.", + "status": "curated", "subtopic_id": "w4-string-operations-and-methods-core", - "subtopic_title": "Slicing with Step, Search, replace, join, strip, and the string Module", - "title": "s1 = ' fgedeef '", - "source": "s1 = ' fgedeef '\nprint(s1.strip(' '))\nprint(s1.strip('f'))\nprint(s1.strip(' f'))", - "outputs": [] + "subtopic_title": "Slicing with Step, Search, replace, join, strip, and the string Module" + }, + { + "id": "manual-string-repetition", + "kind": "correct", + "title": "Repeat text with string multiplication", + "code": "print(3 * \"ha\")\nprint(\"ab\" * 2)", + "output": "hahaha\nabab", + "why": "Both `n * text` and `text * n` repeat the string `n` times, which is a common concise exam pattern.", + "status": "curated", + "subtopic_id": "w4-string-operations-and-methods-core", + "subtopic_title": "Slicing with Step, Search, replace, join, strip, and the string Module" } ], "ai_summary": { @@ -10390,51 +10637,50 @@ "generator": "lecture-first-build", "model": null }, - "ai_common_questions": { - "status": "curated", - "bullets": [ - "Suppose that you'd like to create a new DataFrame that contains only column 'B' for rows with indices 2, 4, and 6. Which of the following code lines will achieve what you want?", - "l2=l1 vs l2=l1[:] — l2=l1 shares the SAME object, slicing creates independent copy", - "range(1,10,3)→[1,4,7] not including 10; l[2:7] goes up to but not including index 7", - "l[::-2] starts from last element going backwards with step 2. l[::2][::-1] first takes every other starting from 0, then reverses — different result" - ], - "items": [ - { - "id": "aiq-2", - "summary": "What does the slice s[::-2] do for the string s = 'abcdef'?", - "detail": "The step -2 reverses the string and skips every second character, starting from the end ('f', then 'd', then 'b').", - "extra": "String Slicing", - "subtopic_id": "w4-string-operations-and-methods-core", - "subtopic_title": "Slicing with Step, Search, replace, join, strip, and the string Module" - }, - { - "id": "aiq-5", - "summary": "Slicing creates a NEW object", - "detail": "l2=l1 vs l2=l1[:] — l2=l1 shares the SAME object, slicing creates independent copy", - "extra": "", - "subtopic_id": "", - "subtopic_title": "" + "exam_questions": [ + { + "id": "exam-intro_python_sample_final_24_25-4-w2-conditions", + "exam_label": "intro_python_sample_final_24_25", + "exam_source": "materials/post_midterm/Sample Final plus answers.pdf", + "year": "2024", + "number": 4, + "week": 4, + "topic": "String Methods", + "subtopic_id": "w4-string-operations-and-methods-core", + "subtopic_title": "Slicing with Step, Search, replace, join, strip, and the string Module", + "question": "Which of the following code segments does NOT achieve the goal of returning a string with 10 digits by removing dashes?", + "code_context": "", + "options": { + "A": "def format_phone_number(number):\n number.replace(\"-\", \"\")\n return number", + "B": "def format_phone_number(number):\n return number.replace(\"-\", \"\")", + "C": "def format_phone_number(number):\n digits = []\n for char in number:\n if char in \"0123456789\":\n digits.append(char)\n return \"\".join(digits)", + "D": "def format_phone_number(number):\n return \"\".join(number.split(\"-\"))" }, - { - "id": "aiq-6", - "summary": "range() and slicing both exclusive at stop", - "detail": "range(1,10,3)→[1,4,7] not including 10; l[2:7] goes up to but not including index 7", - "extra": "", - "subtopic_id": "", - "subtopic_title": "" + "correct": "A", + "explanation": "Strings in Python are immutable. The .replace() method returns a new string but does not modify the original. Option A returns the original string with dashes because the result of .replace() was not assigned back to the variable." + }, + { + "id": "exam-intro_python_sample_final_24_25-22-w2-conditions", + "exam_label": "intro_python_sample_final_24_25", + "exam_source": "materials/post_midterm/Sample Final plus answers.pdf", + "year": "2024", + "number": 22, + "week": 4, + "topic": "String Methods", + "subtopic_id": "w4-string-operations-and-methods-core", + "subtopic_title": "Slicing with Step, Search, replace, join, strip, and the string Module", + "question": "Which script, using the count string method, would print the value 1 for x = 'Amsterdam'?", + "code_context": "x = 'Amsterdam'", + "options": { + "A": "print(count(x, 'a'))", + "B": "print(x.count('a'))", + "C": "Both scripts would deliver that result", + "D": "Neither script would deliver that result" }, - { - "id": "manual-find-vs-index", - "summary": "What is the difference between `s.find(x)` and `s.index(x)` when `x` is missing?", - "detail": "`find` returns `-1`; `index` raises `ValueError`.", - "extra": "", - "code": "s = 'banana'\nprint(s.find('x'))\nprint(s.index('x')) # ValueError", - "table": null - } - ], - "generator": "lecture-first-build", - "model": null - }, + "correct": "B", + "explanation": "The count() method is a string method, not a standalone function. It is called using the dot notation on a string object." + } + ], "key_points_to_remember": [ { "id": "kp-1", @@ -10565,133 +10811,254 @@ "subtopic_title": "Slicing with Step, Search, replace, join, strip, and the string Module", "details": [ { - "id": "kp-6-d1", - "kind": "example", - "title": "Stripping whitespace and characters", - "code": "s = ' abc '\nprint(s.strip()) # 'abc'\ns2 = 'eeabcdee'\nprint(s2.strip('e')) # 'abcd'" + "id": "kp-6-d1", + "kind": "example", + "title": "Stripping whitespace and characters", + "code": "s = ' abc '\nprint(s.strip()) # 'abc'\ns2 = 'eeabcdee'\nprint(s2.strip('e')) # 'abcd'" + } + ] + }, + { + "id": "kp-7", + "text": "Pattern to remember: `find` returns `-1`; `index` raises `ValueError` if the substring is missing.", + "status": "curated", + "generator": "lecture-first-build", + "model": null, + "subtopic_id": "w4-string-operations-and-methods-core", + "subtopic_title": "Slicing with Step, Search, replace, join, strip, and the string Module", + "details": [] + }, + { + "id": "kp-manual-string-method-results", + "text": "String methods like `replace`, `capitalize`, `split`, and `join` return new values; the original string stays unchanged unless you assign the result.", + "status": "curated", + "generator": "manual-gap-merge-rm008", + "model": null, + "subtopic_id": "w4-string-operations-and-methods-core", + "subtopic_title": "Slicing with Step, Search, replace, join, strip, and the string Module", + "details": [ + { + "id": "kp-manual-string-method-results-d1", + "kind": "example", + "title": "replace() returns a new string", + "code": "number = '020-525-1400'\ncleaned = number.replace('-', '')\nprint(number) # '020-525-1400'\nprint(cleaned) # '0205251400'" + } + ] + } + ], + "lecture_snippets": [ + { + "id": "ks-5198d93ec1", + "week": 4, + "source": "materials/post_midterm/Lecture Week 4.pptx", + "source_type": "lecture", + "topic": "String Operations and Methods", + "subtopic_id": "w4-string-operations-and-methods-core", + "subtopic_title": "Slicing with Step, Search, replace, join, strip, and the string Module", + "title": "String Searching: find vs index", + "explanation": "Both find() and index() search for a substring. The key difference is that find() returns -1 if the substring is not found, while index() raises a ValueError.", + "code_examples": [ + { + "description": "Behavior when substring is missing", + "code": "s = 'abc'\nprint(s.find('z')) # -1\n# print(s.index('z')) # Raises ValueError" + } + ] + }, + { + "id": "ks-f80f1bf556", + "week": 4, + "source": "materials/post_midterm/Lecture Week 4.pptx", + "source_type": "lecture", + "topic": "String Operations and Methods", + "subtopic_id": "w4-string-operations-and-methods-core", + "subtopic_title": "Slicing with Step, Search, replace, join, strip, and the string Module", + "title": "String Slicing with Step", + "explanation": "Slicing allows a third parameter 'step'. s[::2] takes every second character, while s[::-1] reverses the string.", + "code_examples": [ + { + "description": "Slicing examples", + "code": "s = '01234567'\nprint(s[::4]) # '04'\nprint(s[::-2]) # '7531'" + } + ] + }, + { + "id": "ks-cdb152720e", + "week": 4, + "source": "materials/post_midterm/Lecture Week 4.pptx", + "source_type": "lecture", + "topic": "String Operations and Methods", + "subtopic_id": "w4-string-operations-and-methods-core", + "subtopic_title": "Slicing with Step, Search, replace, join, strip, and the string Module", + "title": "The join Method", + "explanation": "The join() method takes an iterable (like a list) and concatenates its elements using the string it is called on as a separator.", + "code_examples": [ + { + "description": "Joining a list into a string", + "code": "words = ['a', 'b', 'c']\nprint('-'.join(words)) # 'a-b-c'\nprint(''.join(words)) # 'abc'" + } + ] + }, + { + "id": "ks-45aead894c", + "week": 4, + "source": "materials/post_midterm/Lecture Week 4.pptx", + "source_type": "lecture", + "topic": "String Operations and Methods", + "subtopic_id": "w4-string-operations-and-methods-core", + "subtopic_title": "Slicing with Step, Search, replace, join, strip, and the string Module", + "title": "The replace Method", + "explanation": "Replaces occurrences of a substring. It accepts an optional 'count' argument to limit the number of replacements.", + "code_examples": [ + { + "description": "Limiting replacements", + "code": "s = 'aaaa'\nprint(s.replace('a', 'b', 2)) # 'bbaa'" + } + ] + }, + { + "id": "ks-bdea67862f", + "week": 4, + "source": "materials/post_midterm/Lecture Week 4.pptx", + "source_type": "lecture", + "topic": "String Operations and Methods", + "subtopic_id": "w4-string-operations-and-methods-core", + "subtopic_title": "Slicing with Step, Search, replace, join, strip, and the string Module", + "title": "The string Module", + "explanation": "The 'string' module provides pre-defined constants like all lowercase letters, digits, and punctuation.", + "code_examples": [ + { + "description": "Importing string constants", + "code": "import string\nprint(string.ascii_lowercase) # 'abcdef...'\nprint(string.digits) # '0123456789'" } ] }, { - "id": "kp-7", - "text": "Pattern to remember: `find` returns `-1`; `index` raises `ValueError` if the substring is missing.", - "status": "curated", - "generator": "lecture-first-build", - "model": null, - "subtopic_id": "w4-string-operations-and-methods-core", - "subtopic_title": "Slicing with Step, Search, replace, join, strip, and the string Module", - "details": [] - }, - { - "id": "kp-manual-string-method-results", - "text": "String methods like `replace`, `capitalize`, `split`, and `join` return new values; the original string stays unchanged unless you assign the result.", - "status": "curated", - "generator": "manual-gap-merge-rm008", - "model": null, + "id": "ks-e4dc502d3e", + "week": 4, + "source": "materials/post_midterm/Lecture Week 4.pptx", + "source_type": "lecture", + "topic": "String Operations and Methods", "subtopic_id": "w4-string-operations-and-methods-core", "subtopic_title": "Slicing with Step, Search, replace, join, strip, and the string Module", - "details": [ + "title": "String Stripping", + "explanation": "strip() removes leading and trailing characters. lstrip() and rstrip() target the left and right sides respectively.", + "code_examples": [ { - "id": "kp-manual-string-method-results-d1", - "kind": "example", - "title": "replace() returns a new string", - "code": "number = '020-525-1400'\ncleaned = number.replace('-', '')\nprint(number) # '020-525-1400'\nprint(cleaned) # '0205251400'" + "description": "Stripping whitespace and characters", + "code": "s = ' abc '\nprint(s.strip()) # 'abc'\ns2 = 'eeabcdee'\nprint(s2.strip('e')) # 'abcd'" } ] } ], - "ai_examples": [ + "notebook_snippets": [ { - "id": "ai-example-1", - "kind": "correct", - "title": "Behavior when substring is missing", - "code": "s = 'abc'\nprint(s.find('z')) # -1\n# print(s.index('z')) # Raises ValueError", - "why": "Both find() and index() search for a substring. The key difference is that find() returns -1 if the substring is not found, while index() raises a ValueError.", - "output": "", - "status": "curated", + "id": "cs-1c6788a4b3", + "week": 4, + "cell_index": null, + "cell_type": "code", + "source_type": "notebook", + "topic": "String Operations and Methods", "subtopic_id": "w4-string-operations-and-methods-core", - "subtopic_title": "Slicing with Step, Search, replace, join, strip, and the string Module" + "subtopic_title": "Slicing with Step, Search, replace, join, strip, and the string Module", + "title": "s1 = 'abcdefghabcdefgh'", + "source": "s1 = 'abcdefghabcdefgh'\nprint(s1.find('i'))\nprint(s1[s1.find('i')])\nprint(s1.index('i'))", + "outputs": [] }, { - "id": "ai-example-2", - "kind": "correct", - "title": "Slicing examples", - "code": "s = '01234567'\nprint(s[::4]) # '04'\nprint(s[::-2]) # '7531'", - "why": "Slicing allows a third parameter 'step'. s[::2] takes every second character, while s[::-1] reverses the string.", - "output": "", - "status": "curated", + "id": "cs-399e4a20ca", + "week": 4, + "cell_index": null, + "cell_type": "code", + "source_type": "notebook", + "topic": "String Operations and Methods", "subtopic_id": "w4-string-operations-and-methods-core", - "subtopic_title": "Slicing with Step, Search, replace, join, strip, and the string Module" + "subtopic_title": "Slicing with Step, Search, replace, join, strip, and the string Module", + "title": "s1 = 'abcdefghabcdefgh'", + "source": "s1 = 'abcdefghabcdefgh'\nprint(s1.find('e'))\nprint(s1.index('e', 5))\nprint(s1.find('e', 5, 10))\nprint(s1.index('e', 5, 13))\nprint(s1.find('ef'))\nprint(s1.index('q'))", + "outputs": [] }, { - "id": "ai-example-3", - "kind": "correct", - "title": "Joining a list into a string", - "code": "words = ['a', 'b', 'c']\nprint('-'.join(words)) # 'a-b-c'\nprint(''.join(words)) # 'abc'", - "why": "The join() method takes an iterable (like a list) and concatenates its elements using the string it is called on as a separator.", - "output": "", - "status": "curated", + "id": "cs-fe295c3cf2", + "week": 4, + "cell_index": null, + "cell_type": "code", + "source_type": "notebook", + "topic": "String Operations and Methods", "subtopic_id": "w4-string-operations-and-methods-core", - "subtopic_title": "Slicing with Step, Search, replace, join, strip, and the string Module" + "subtopic_title": "Slicing with Step, Search, replace, join, strip, and the string Module", + "title": "s1 = 'abcdabcdabcd'", + "source": "s1 = 'abcdabcdabcd'\nprint(s1.replace('a', 'xx'))\nprint(s1.replace('ab', 'xx', 1))\nprint(s1.replace('abc', 'xx', 2))\nprint(s1.replace('abcd', 'xx', 10))\nprint(s1.replace('a', ''))\nprint(s1.replace('q', 'qq'))", + "outputs": [] }, { - "id": "ai-example-4", - "kind": "correct", - "title": "Limiting replacements", - "code": "s = 'aaaa'\nprint(s.replace('a', 'b', 2)) # 'bbaa'", - "why": "Replaces occurrences of a substring. It accepts an optional 'count' argument to limit the number of replacements.", - "output": "", - "status": "curated", + "id": "cs-c9b5098b60", + "week": 4, + "cell_index": null, + "cell_type": "code", + "source_type": "notebook", + "topic": "String Operations and Methods", "subtopic_id": "w4-string-operations-and-methods-core", - "subtopic_title": "Slicing with Step, Search, replace, join, strip, and the string Module" + "subtopic_title": "Slicing with Step, Search, replace, join, strip, and the string Module", + "title": "print('abacad'.index('ac'))", + "source": "print('abacad'.index('ac'))", + "outputs": [] }, { - "id": "ai-example-5", - "kind": "correct", - "title": "Importing string constants", - "code": "import string\nprint(string.ascii_lowercase) # 'abcdef...'\nprint(string.digits) # '0123456789'", - "why": "The 'string' module provides pre-defined constants like all lowercase letters, digits, and punctuation.", - "output": "", - "status": "curated", + "id": "cs-7956253888", + "week": 4, + "cell_index": null, + "cell_type": "code", + "source_type": "notebook", + "topic": "String Operations and Methods", "subtopic_id": "w4-string-operations-and-methods-core", - "subtopic_title": "Slicing with Step, Search, replace, join, strip, and the string Module" + "subtopic_title": "Slicing with Step, Search, replace, join, strip, and the string Module", + "title": "print(str.index('abacad', 'ac'))", + "source": "print(str.index('abacad', 'ac'))", + "outputs": [] }, { - "id": "ai-example-6", - "kind": "correct", - "title": "Stripping whitespace and characters", - "code": "s = ' abc '\nprint(s.strip()) # 'abc'\ns2 = 'eeabcdee'\nprint(s2.strip('e')) # 'abcd'", - "why": "strip() removes leading and trailing characters. lstrip() and rstrip() target the left and right sides respectively.", - "output": "", - "status": "curated", + "id": "cs-bccefd5e48", + "week": 4, + "cell_index": null, + "cell_type": "code", + "source_type": "notebook", + "topic": "String Operations and Methods", "subtopic_id": "w4-string-operations-and-methods-core", - "subtopic_title": "Slicing with Step, Search, replace, join, strip, and the string Module" + "subtopic_title": "Slicing with Step, Search, replace, join, strip, and the string Module", + "title": "l1 = ['abc', 'de', 'fg', 'h']", + "source": "l1 = ['abc', 'de', 'fg', 'h']\nprint('xy'.join(l1))\nprint(''.join(l1))", + "outputs": [] }, { - "id": "ai-example-7", - "kind": "correct", - "title": "s1 = 'abcdefghabcdefgh'", - "code": "s1 = 'abcdefghabcdefgh'\nprint(s1.find('i'))\nprint(s1[s1.find('i')])\nprint(s1.index('i'))", - "why": "", - "output": "", - "status": "curated", + "id": "cs-be799f0dcb", + "week": 4, + "cell_index": null, + "cell_type": "code", + "source_type": "notebook", + "topic": "String Operations and Methods", "subtopic_id": "w4-string-operations-and-methods-core", - "subtopic_title": "Slicing with Step, Search, replace, join, strip, and the string Module" + "subtopic_title": "Slicing with Step, Search, replace, join, strip, and the string Module", + "title": "a =sorted('0123456789', key=lambda x: str(int(x) % 2 == 1) + x)", + "source": "a =sorted('0123456789', key=lambda x: str(int(x) % 2 == 1) + x)\nprint(''.join(a))", + "outputs": [] }, { - "id": "ai-example-8", - "kind": "correct", - "title": "s1 = 'abcdefghabcdefgh'", - "code": "s1 = 'abcdefghabcdefgh'\nprint(s1.find('e'))\nprint(s1.index('e', 5))\nprint(s1.find('e', 5, 10))\nprint(s1.index('e', 5, 13))\nprint(s1.find('ef'))\nprint(s1.index('q'))", - "why": "", - "output": "", - "status": "curated", + "id": "cs-3267796c45", + "week": 4, + "cell_index": null, + "cell_type": "code", + "source_type": "notebook", + "topic": "String Operations and Methods", "subtopic_id": "w4-string-operations-and-methods-core", - "subtopic_title": "Slicing with Step, Search, replace, join, strip, and the string Module" + "subtopic_title": "Slicing with Step, Search, replace, join, strip, and the string Module", + "title": "s1 = ' fgedeef '", + "source": "s1 = ' fgedeef '\nprint(s1.strip(' '))\nprint(s1.strip('f'))\nprint(s1.strip(' f'))", + "outputs": [] } ], "recommended_ids": [ - "exam-intro_python_sample_final_24_25-6-w4-string-operations-and-methods", + "exam-intro_python_sample_final_24_25-4-w2-conditions", + "exam-intro_python_sample_final_24_25-22-w2-conditions", "ks-5198d93ec1", "ks-f80f1bf556", "ks-cdb152720e", @@ -10699,8 +11066,115 @@ "cs-1c6788a4b3", "cs-399e4a20ca", "cs-fe295c3cf2" - ] - } + ], + "homework_snippets": [], + "homework_recommended_ids": [] + }, + "subtopics": [ + { + "id": "w4-string-operations-and-methods-core", + "item_ids": { + "exam_question_ids": [ + "exam-intro_python_sample_final_24_25-4-w2-conditions", + "exam-intro_python_sample_final_24_25-22-w2-conditions" + ], + "example_ids": [ + "ai-example-1", + "ai-example-2", + "ai-example-3", + "ai-example-4", + "ai-example-5", + "ai-example-6", + "ai-example-7", + "ai-example-8", + "manual-string-format-method", + "manual-string-islower-method", + "manual-string-repetition" + ], + "key_point_ids": [ + "kp-1", + "kp-2", + "kp-3", + "kp-4", + "kp-5", + "kp-6", + "kp-7", + "kp-manual-string-method-results" + ], + "lecture_snippet_ids": [ + "ks-5198d93ec1", + "ks-f80f1bf556", + "ks-cdb152720e", + "ks-45aead894c", + "ks-bdea67862f", + "ks-e4dc502d3e" + ], + "notebook_snippet_ids": [ + "cs-1c6788a4b3", + "cs-399e4a20ca", + "cs-fe295c3cf2", + "cs-c9b5098b60", + "cs-7956253888", + "cs-bccefd5e48", + "cs-be799f0dcb", + "cs-3267796c45" + ] + }, + "order": 1, + "summary": "Trace string slicing, search, replacement, splitting, joining, and stripping. Compare `.find` versus `.index`, and remember `join` is called on the separator.", + "title": "Slicing with Step, Search, replace, join, strip, and the string Module" + } + ], + "topic": "String Operations and Methods", + "topic_meta": { + "week": 4, + "week_id": "week-4", + "week_title": "Week 4", + "topic_id": "w4-string-operations-and-methods", + "topic_title": "String Operations and Methods", + "topic_order": 2 + }, + "trap_patterns": [ + { + "pattern": "Slicing creates a NEW object", + "trap": "l2=l1 vs l2=l1[:] — l2=l1 shares the SAME object, slicing creates independent copy", + "weeks": [ + 1 + ], + "appears_in_exams": [ + "trial_midterm", + "midterm_2023", + "midterm_2024", + "extra_practice" + ] + }, + { + "pattern": "range() and slicing both exclusive at stop", + "trap": "range(1,10,3)→[1,4,7] not including 10; l[2:7] goes up to but not including index 7", + "weeks": [ + 1, + 2 + ], + "appears_in_exams": [ + "trial_midterm", + "extra_practice" + ] + }, + { + "pattern": "Negative slicing with step=-2", + "trap": "l[::-2] starts from last element going backwards with step 2. l[::2][::-1] first takes every other starting from 0, then reverses — different result", + "weeks": [ + 1 + ], + "appears_in_exams": [ + "extra_practice" + ] + } + ], + "week_id": "week-4", + "weeks": [ + 4 + ] }, { "id": "w4-string-formatting", @@ -10954,70 +11428,13 @@ "ks-72dda5450c", "ks-ea5a4acb43", "ks-acb7f400b2" - ] + ], + "homework_snippets": [], + "homework_recommended_ids": [] } }, { - "id": "w4-oop-fundamentals", - "topic": "OOP Fundamentals", "canonical_topic": "w4-oop-fundamentals", - "weeks": [ - 4 - ], - "week_id": "week-4", - "topic_meta": { - "week": 4, - "week_id": "week-4", - "week_title": "Week 4", - "topic_id": "w4-oop-fundamentals", - "topic_title": "OOP Fundamentals", - "topic_order": 4 - }, - "subtopics": [ - { - "id": "w4-oop-fundamentals-core", - "title": "Class Definition, __init__, self, and Attribute Basics", - "order": 1, - "summary": "A class defines attributes and methods; `__init__` runs when you create an object and stores instance data on `self`.", - "item_ids": { - "lecture_snippet_ids": [ - "ks-06b21ad349", - "ks-9e278d1ee6", - "ks-5cbba26b09" - ], - "exam_question_ids": [ - "exam-Test Exam 07-06-22-1-w4-oop-fundamentals", - "exam-Test Exam 07-06-22-2-w4-oop-fundamentals", - "exam-Trial final exam Introduction to Python-1-w4-oop-fundamentals", - "exam-Trial final exam Introduction to Python-2-w4-oop-fundamentals" - ], - "notebook_snippet_ids": [ - "cs-0d319e4faf", - "cs-30e53467b8", - "cs-e0dffaa52d", - "cs-9bc6869c46", - "cs-e76e122239", - "cs-040220fa7e", - "cs-f73de78062" - ], - "example_ids": [ - "ai-example-1", - "ai-example-2", - "ai-example-3", - "ai-example-6", - "manual-oop-init-defaults", - "manual-oop-attrs" - ], - "key_point_ids": [ - "kp-1", - "kp-2", - "kp-3", - "kp-4", - "kp-manual-init-defaults" - ] - } - } - ], "exam_stats": { "total_hits": 4, "by_exam": { @@ -11026,85 +11443,146 @@ }, "coverage_count": 2 }, + "id": "w4-oop-fundamentals", "related_topics": [ "Class Definition, __init__, self, and Attribute Basics" ], - "trap_patterns": [ - { - "pattern": "1 + True = 2 (bool is subclass of int)", - "trap": "True==1, False==0 in numeric contexts. type(True)==int is False but isinstance(True,int) is True", - "weeks": [ - 2 + "sections": { + "ai_common_questions": { + "status": "curated", + "bullets": [ + "Given the class definition above, trying to execute the following two code lines will result in a Python error.\nmy_flight = Flight(\"KLM\", \"Amsterdam\", \"Paris\") # Code line 1\nmy_flight.set_date(my_flight, \"29-02-2022\")…", + "Suppose that you also want to write a method called compare that compares the book to another book and gives a recommendation for which one to read. A book is better than another book if its average review score is higher than the second book's and it has at…", + "You'd like to define a class called Vehicle. It should have two attributes: \"name\" and \"mode\", which you want to be initialized at the time of object construction.\n\nThe \"name\" attribute can be any string, and it must be passed to the object constructor. The \"…", + "Take a look at the following class definition.\n\nSuppose that we create a Book object and call its add_review method three times, like this:\nbook_1 = Book(\"The Lightning Thief\", \"Rick Riordan\")\nbook_1.add_review(5)\nbook_1.add_review(3)\nbook_1.add_review(3)\n\nWh…", + "True==1, False==0 in numeric contexts. type(True)==int is False but isinstance(True,int) is True", + "Looping directly over a dict iterates over keys only" ], - "appears_in_exams": [ - "midterm_2023" - ] - }, - { - "pattern": "for key in dict == for key in dict.keys()", - "trap": "Looping directly over a dict iterates over keys only", - "weeks": [ - 2 + "items": [ + { + "id": "manual-self", + "summary": "Why is `self` the first parameter of an instance method?", + "detail": "`self` is the current object, so the method can read and update that object's attributes.", + "extra": "", + "code": "class Flight:\n def set_date(self, date):\n self.date = date", + "table": null + }, + { + "id": "manual-method-call", + "summary": "Why does `obj.set_date(obj, x)` pass too many arguments?", + "detail": "When you call a method on an object, Python passes the object as `self` automatically. Writing it again adds one argument too many.", + "extra": "", + "code": "obj.set_date(x) # correct\nobj.set_date(obj, x) # too many args", + "table": null + }, + { + "id": "manual-init-default", + "summary": "How do default values in `__init__` make constructor arguments optional?", + "detail": "A default like `vehicle_mode='land'` can be omitted when the object is created, but the instance still receives that attribute value.", + "extra": "", + "code": "class Vehicle:\n def __init__(self, name, vehicle_mode='land'):\n self.name = name\n self.vehicle_mode = vehicle_mode", + "table": null + } ], - "appears_in_exams": [ - "midterm_2023" - ] - } - ], - "sections": { - "lecture_snippets": [ + "generator": "lecture-first-build", + "model": null + }, + "ai_examples": [ { - "id": "ks-06b21ad349", - "week": 4, - "source": "materials/post_midterm/Lecture Week 4.pptx", - "source_type": "lecture", - "topic": "OOP Fundamentals", + "id": "ai-example-1", + "kind": "correct", + "title": "Defining a simple class", + "code": "class Car:\n def __init__(self, color):\n self.color = color", + "why": "A class defines methods and attribute layout; `__init__` runs when you create an object and stores instance data on `self`.", + "output": "", + "status": "curated", "subtopic_id": "w4-oop-fundamentals-core", - "subtopic_title": "Class Definition, __init__, self, and Attribute Basics", - "title": "Class Definition and __init__", - "explanation": "A class is a blueprint. The __init__ method is the constructor called automatically when a new object is created to initialize attributes.", - "code_examples": [ - { - "description": "Defining a simple class", - "code": "class Car:\n def __init__(self, color):\n self.color = color" - } - ] + "subtopic_title": "Class Definition, __init__, self, and Attribute Basics" }, { - "id": "ks-9e278d1ee6", - "week": 4, - "source": "materials/post_midterm/Lecture Week 4.pptx", - "source_type": "lecture", - "topic": "OOP Fundamentals", + "id": "ai-example-2", + "kind": "correct", + "title": "Using self to access attributes", + "code": "class Dog:\n def __init__(self, name):\n self.name = name\n def bark(self):\n return f'{self.name} says woof!'", + "why": "`self` refers to the current instance, so instance methods read and write data through `self.attr`.", + "output": "", + "status": "curated", "subtopic_id": "w4-oop-fundamentals-core", - "subtopic_title": "Class Definition, __init__, self, and Attribute Basics", - "title": "The self Parameter", - "explanation": "In class methods, 'self' refers to the specific instance of the object. It must be the first parameter of any instance method.", - "code_examples": [ - { - "description": "Using self to access attributes", - "code": "class Dog:\n def __init__(self, name):\n self.name = name\n def bark(self):\n return f'{self.name} says woof!'" - } - ] + "subtopic_title": "Class Definition, __init__, self, and Attribute Basics" }, { - "id": "ks-5cbba26b09", - "week": 4, - "source": "materials/post_midterm/Lecture Week 4.pptx", - "source_type": "lecture", - "topic": "OOP Fundamentals", + "id": "ai-example-3", + "kind": "correct", + "title": "Shared class attribute", + "code": "class Counter:\n count = 0\n def __init__(self):\n Counter.count += 1", + "why": "`self.x` is per object; a class attribute is shared until an instance shadows it with its own value.", + "output": "", + "status": "curated", "subtopic_id": "w4-oop-fundamentals-core", - "subtopic_title": "Class Definition, __init__, self, and Attribute Basics", - "title": "Class vs Instance Attributes", - "explanation": "Instance attributes (self.x) are unique to each object. Class attributes are defined outside methods and shared by all instances of the class.", - "code_examples": [ - { - "description": "Shared class attribute", - "code": "class Counter:\n count = 0\n def __init__(self):\n Counter.count += 1" - } - ] + "subtopic_title": "Class Definition, __init__, self, and Attribute Basics" + }, + { + "id": "ai-example-6", + "kind": "correct", + "title": "Subclassing `str`", + "code": "#\nclass New_str(str):\n def index(self, needle, start = 0):\n return self.find(needle, start)\n\na = New_str(\"abcd\")\nprint(a.upper()) \nprint(a.find(\"d\")) \nprint(a.find(\"e\")) \nprint(a.index(\"d\")) \nprint(a.index(\"e\"))", + "why": "You can subclass a built-in type to add custom methods while keeping the original string behavior.", + "output": "", + "status": "curated", + "subtopic_id": "w4-oop-fundamentals-core", + "subtopic_title": "Class Definition, __init__, self, and Attribute Basics" + }, + { + "id": "manual-oop-attrs", + "kind": "correct", + "title": "Class attribute vs instance attribute", + "code": "class Rectangle:\n units = 'cm'\n\n def __init__(self, width):\n self.width = width\n\nr1 = Rectangle(3)\nr2 = Rectangle(5)\nr2.units = 'm'\nprint(r1.units, r2.units)", + "output": "cm m", + "why": "`self.width` is per object; `Class.units` is shared until an instance shadows it with its own attribute.", + "status": "curated", + "subtopic_id": "w4-oop-fundamentals-core", + "subtopic_title": "Class Definition, __init__, self, and Attribute Basics" + }, + { + "id": "manual-oop-init-defaults", + "kind": "correct", + "title": "Safe default state in `__init__`", + "code": "class Book:\n def __init__(self, title, review_scores=None):\n self.title = title\n self.review_scores = [] if review_scores is None else review_scores", + "output": "", + "why": "Constructor defaults can make arguments optional, but mutable per-instance state should start from `None` and be created inside `__init__`.", + "status": "curated", + "subtopic_id": "w4-oop-fundamentals-core", + "subtopic_title": "Class Definition, __init__, self, and Attribute Basics" + }, + { + "id": "manual-oop-constructor-defaults", + "kind": "correct", + "title": "Constructor defaults belong in `__init__` parameters", + "code": "class Vehicle:\n def __init__(self, name, mode=\"land\"):\n self.name = name\n self.mode = mode\n\ncar = Vehicle(\"Mazda\")\nprint(car.name, car.mode)", + "output": "Mazda land", + "why": "Default constructor arguments let an instance omit optional information while still giving `self` a predictable initial state.", + "status": "curated", + "subtopic_id": "w4-oop-fundamentals-core", + "subtopic_title": "Class Definition, __init__, self, and Attribute Basics" + }, + { + "id": "manual-oop-state-compare", + "kind": "correct", + "title": "Trace `self` state across multiple method calls", + "code": "class Book:\n def __init__(self, title):\n self.title = title\n self.scores = []\n\n def add_review(self, score):\n self.scores.append(score)\n\n def average(self):\n return sum(self.scores) / len(self.scores)\n\n def better_than(self, other):\n return self.average() > other.average()\n\nbook_1 = Book(\"A\")\nbook_2 = Book(\"B\")\nfor score in [5, 3, 3]:\n book_1.add_review(score)\nfor score in [4, 4, 4]:\n book_2.add_review(score)\nprint(book_1.better_than(book_2))", + "output": "False", + "why": "Exam OOP reasoning often hinges on updating `self` in one method and then comparing derived state in a later method call.", + "status": "curated", + "subtopic_id": "w4-oop-fundamentals-core", + "subtopic_title": "Class Definition, __init__, self, and Attribute Basics" } ], + "ai_summary": { + "status": "curated", + "content": "A class defines attributes and methods; `__init__` runs when you create an object, defaults can make constructor arguments optional, and class attributes are shared across instances.", + "generator": "lecture-first-build", + "model": null + }, "exam_questions": [ { "id": "exam-Test Exam 07-06-22-1-w4-oop-fundamentals", @@ -11189,150 +11667,50 @@ }, "correct": "a", "explanation": "The list of review scores is [5, 3, 3]. The sum is 11, and the length is 3. 11 / 3 is approximately 3.666... Using `round(..., 1)` rounds this float to one decimal place, resulting in 3.7." - } - ], - "notebook_snippets": [ - { - "id": "cs-0d319e4faf", - "week": 4, - "cell_index": null, - "cell_type": "code", - "source_type": "notebook", - "topic": "OOP Fundamentals", - "subtopic_id": "w4-oop-fundamentals-core", - "subtopic_title": "Class Definition, __init__, self, and Attribute Basics", - "title": "class Rectangle:", - "source": "class Rectangle:\n total_size = 0\n def __init__(self, length, width=1):\n self.length = length\n self.width = width\n Rectangle.total_size += self.length * self.width\n print(f'{self.length} by {self.width} created, {Rectangle.total_size = }')\n def size(self, data_type=int):\n return f\"The size = {data_type(self.length * self.width)}.\"\n def __del__(self):\n Rectangle.total_size -= self.length * self.width\n print(f'{self.length} by {self.width} deleted, {Rectangle.total_size = }')\n \nprint(Rectangle.total_size)\nrectangle_1 = Rectangle(2,3) \nrectangle_2 = Rectangle(2)\ndel rectangle_1 \ndel rectangle_2", - "outputs": [ - "0\n2 by 3 created, Rectangle.total_size = 6\n2 by 1 created, Rectangle.total_size = 8\n2 by 3 deleted, Rectangle.total_size = 2\n2 by 1 deleted, Rectangle.total_size = 0" - ] - }, - { - "id": "cs-30e53467b8", - "week": 4, - "cell_index": null, - "cell_type": "code", - "source_type": "notebook", - "topic": "OOP Fundamentals", - "subtopic_id": "w4-oop-fundamentals-core", - "subtopic_title": "Class Definition, __init__, self, and Attribute Basics", - "title": "class Rectangle:", - "source": "class Rectangle:\n total_size = 0\n def __init__(self, length, width=1):\n self.length = length\n self.width = width\n Rectangle.total_size += self.length * self.width\n print(f'rectangle {self.length} by {self.width} created\\n{Rectangle.total_size = }')\n def size(self, data_type=int):\n return f\"The size = {data_type(self.length * self.width)}.\"\n def __del__(self):\n Rectangle.total_size -= self.length * self.width\n print(f'rectangle {self.length} by {self.width} deleted\\n{Rectangle.total_size = }')\n \nprint(Rectangle.total_size)\nrectangle_1 = Rectangle(2,3)\nrectangle_2 = Rectangle(3)\nrectangle_3 = Rectangle(2,2)\n\ndel rectangle_1\ndel rectangle_3\ndel rectangle_2", - "outputs": [ - "0\nrectangle 2 by 3 created\nRectangle.total_size = 6\nrectangle 3 by 1 created\nRectangle.total_size = 9\nrectangle 2 by 2 created\nRectangle.total_size = 13\nrectangle 2 by 3 deleted\nRectangle.total_size = 7\nrectangle 2 by 2 deleted\nRectangle.total_size = 3\nrectangle 3 by 1 deleted\nRectangle.total_size = 0" - ] - }, - { - "id": "cs-e0dffaa52d", - "week": 4, - "cell_index": null, - "cell_type": "code", - "source_type": "notebook", - "topic": "OOP Fundamentals", - "subtopic_id": "w4-oop-fundamentals-core", - "subtopic_title": "Class Definition, __init__, self, and Attribute Basics", - "title": "class New_str(str):", - "source": "#\nclass New_str(str):\n def index(self, needle, start = 0):\n return self.find(needle, start)\n\na = New_str(\"abcd\")\nprint(a.upper()) \nprint(a.find(\"d\")) \nprint(a.find(\"e\")) \nprint(a.index(\"d\")) \nprint(a.index(\"e\"))", - "outputs": [] - }, - { - "id": "cs-9bc6869c46", - "week": 4, - "cell_index": null, - "cell_type": "code", - "source_type": "notebook", - "topic": "OOP Fundamentals", - "subtopic_id": "w4-oop-fundamentals-core", - "subtopic_title": "Class Definition, __init__, self, and Attribute Basics", - "title": "class Rectangle:", - "source": "#\nclass Rectangle:\n def __init__(self, length, width=1):\n self.length = length\n self.width = width\n def info_about_attribute_a(self):\n return f'{Rectangle.a=}, {self.a=}'\n\nrectangle_1 = Rectangle(2,3)\nRectangle.a = 5\nrectangle_1.a = 10\nprint(Rectangle.a, rectangle_1.a)\nprint(rectangle_1.info_about_attribute_a())", - "outputs": [] - }, - { - "id": "cs-e76e122239", - "week": 4, - "cell_index": null, - "cell_type": "code", - "source_type": "notebook", - "topic": "OOP Fundamentals", - "subtopic_id": "w4-oop-fundamentals-core", - "subtopic_title": "Class Definition, __init__, self, and Attribute Basics", - "title": "class Rectangle:", - "source": "class Rectangle:\n def __init__(self, length, width=1):\n self.length = length\n self.width = width\n def size(self, data_type=int):\n return f\"The size = {data_type(self.length * self.width)}.\"\nrectangle_1 = Rectangle(2,3)\nrectangle_2 = Rectangle(3)\nrectangle_3 = Rectangle(2,2)\nfor object in [rectangle_1, rectangle_2, rectangle_3, Rectangle(4,4)]:\n print(object.size(float))", - "outputs": [] }, { - "id": "cs-040220fa7e", + "id": "exam-intro_python_sample_final_24_25-1-w5-pandas-core-structures", + "exam_label": "intro_python_sample_final_24_25", + "exam_source": "materials/post_midterm/Sample Final plus answers.pdf", + "year": "2024", + "number": 1, "week": 4, - "cell_index": null, - "cell_type": "code", - "source_type": "notebook", - "topic": "OOP Fundamentals", + "topic": "OOP (Initializers)", "subtopic_id": "w4-oop-fundamentals-core", "subtopic_title": "Class Definition, __init__, self, and Attribute Basics", - "title": "class Rectangle:", - "source": "class Rectangle:\n def __init__(self, length, width=1):\n self.length = length\n self.width = width\n def size(self, data_type=int):\n return f\"The size = {data_type(self.length * self.width)}.\"\n \nrectangle_1 = Rectangle(2,3)\nrectangle_2 = Rectangle(3)\nrectangle_3 = Rectangle(2,2)\nfor object in [rectangle_1, rectangle_2, rectangle_3, Rectangle(4,4)]:\n print(Rectangle.size(object))", - "outputs": [] + "question": "You'd like to define a class called Vehicle. It should have two attributes: name and mode, which you want to be initialized during object creation. The name attribute can be any string, and it must be passed to the object during creation. The mode attribute is also a string, but it doesn't necessarily need to be passed to the object constructor. If it isn't specified at object construction, then the mode attribute should be equal to the string \"land\". Which of the following code segments achieves what you want?", + "code_context": "my_car = Vehicle(\"Mazda\")\n# Expected: my_car.name == \"Mazda\" and my_car.mode == \"land\"", + "options": { + "A": "class Vehicle:\n def __init__(self, vehicle_name, vehicle_mode=\"land\"):\n self.name = vehicle_name\n self.mode = vehicle_mode", + "B": "class Vehicle:\n def __init__(self, vehicle_name, vehicle_mode):\n self.name = vehicle_name\n self.mode = vehicle_mode", + "C": "class Vehicle:\n def __init__(self, vehicle_name, vehicle_mode=\"land\"):\n return name, mode", + "D": "class Vehicle:\n def __init__(vehicle_name, vehicle_mode):\n name = vehicle_name\n mode = vehicle_mode" + }, + "correct": "A", + "explanation": "In Python, default parameter values in the __init__ method allow for optional arguments during object creation. Option A correctly assigns the parameters to instance attributes." }, { - "id": "cs-f73de78062", + "id": "exam-intro_python_sample_final_24_25-2-w5-pandas-core-structures", + "exam_label": "intro_python_sample_final_24_25", + "exam_source": "materials/post_midterm/Sample Final plus answers.pdf", + "year": "2024", + "number": 2, "week": 4, - "cell_index": null, - "cell_type": "code", - "source_type": "notebook", - "topic": "OOP Fundamentals", + "topic": "OOP (Methods)", "subtopic_id": "w4-oop-fundamentals-core", "subtopic_title": "Class Definition, __init__, self, and Attribute Basics", - "title": "class Rectangle:", - "source": "class Rectangle:\n def __init__(self, length, width=1):\n self.length = length\n self.width = width\n def size(self, data_type=int):\n return f\"The size = {data_type(self.length * self.width)}.\"\n \nrectangle_1 = Rectangle(2,3)\nrectangle_2 = Rectangle(3)\nrectangle_3 = Rectangle(2,2)\n\nprint(rectangle_1.size())\nprint(rectangle_2.size(float))\nprint(rectangle_3.size(int))\nprint(Rectangle(4,4).size(str))", - "outputs": [] + "question": "Suppose that we create a Book object and call its add_review method three times, like this: book_1 = Book(\"The Lightning Thief\", \"Rick Riordan\"), book_1.add_review(5), book_1.add_review(3), book_1.add_review(3). What will then the following command print to the screen? print(book_1.show_rating())", + "code_context": "class Book:\n def __init__(self, title, author, review_scores=None):\n self.title = title\n self.author = author\n self.review_scores = review_scores if review_scores else []\n def add_review(self, score):\n self.review_scores.append(score)\n def show_rating(self):\n if self.review_scores:\n return round(sum(self.review_scores) / len(self.review_scores), 1)", + "options": { + "A": "3.7", + "B": "4", + "C": "None", + "D": "3.67" + }, + "correct": "A", + "explanation": "The average of scores [5, 3, 3] is 11 / 3 = 3.666... Using round(..., 1) results in 3.7." } ], - "ai_summary": { - "status": "curated", - "content": "A class defines attributes and methods; `__init__` runs when you create an object, defaults can make constructor arguments optional, and class attributes are shared across instances.", - "generator": "lecture-first-build", - "model": null - }, - "ai_common_questions": { - "status": "curated", - "bullets": [ - "Given the class definition above, trying to execute the following two code lines will result in a Python error.\nmy_flight = Flight(\"KLM\", \"Amsterdam\", \"Paris\") # Code line 1\nmy_flight.set_date(my_flight, \"29-02-2022\")…", - "Suppose that you also want to write a method called compare that compares the book to another book and gives a recommendation for which one to read. A book is better than another book if its average review score is higher than the second book's and it has at…", - "You'd like to define a class called Vehicle. It should have two attributes: \"name\" and \"mode\", which you want to be initialized at the time of object construction.\n\nThe \"name\" attribute can be any string, and it must be passed to the object constructor. The \"…", - "Take a look at the following class definition.\n\nSuppose that we create a Book object and call its add_review method three times, like this:\nbook_1 = Book(\"The Lightning Thief\", \"Rick Riordan\")\nbook_1.add_review(5)\nbook_1.add_review(3)\nbook_1.add_review(3)\n\nWh…", - "True==1, False==0 in numeric contexts. type(True)==int is False but isinstance(True,int) is True", - "Looping directly over a dict iterates over keys only" - ], - "items": [ - { - "id": "manual-self", - "summary": "Why is `self` the first parameter of an instance method?", - "detail": "`self` is the current object, so the method can read and update that object's attributes.", - "extra": "", - "code": "class Flight:\n def set_date(self, date):\n self.date = date", - "table": null - }, - { - "id": "manual-method-call", - "summary": "Why does `obj.set_date(obj, x)` pass too many arguments?", - "detail": "When you call a method on an object, Python passes the object as `self` automatically. Writing it again adds one argument too many.", - "extra": "", - "code": "obj.set_date(x) # correct\nobj.set_date(obj, x) # too many args", - "table": null - }, - { - "id": "manual-init-default", - "summary": "How do default values in `__init__` make constructor arguments optional?", - "detail": "A default like `vehicle_mode='land'` can be omitted when the object is created, but the instance still receives that attribute value.", - "extra": "", - "code": "class Vehicle:\n def __init__(self, name, vehicle_mode='land'):\n self.name = name\n self.vehicle_mode = vehicle_mode", - "table": null - } - ], - "generator": "lecture-first-build", - "model": null - }, "key_points_to_remember": [ { "id": "kp-1", @@ -11419,85 +11797,255 @@ ] } ], - "ai_examples": [ + "lecture_snippets": [ { - "id": "ai-example-1", - "kind": "correct", - "title": "Defining a simple class", - "code": "class Car:\n def __init__(self, color):\n self.color = color", - "why": "A class defines methods and attribute layout; `__init__` runs when you create an object and stores instance data on `self`.", - "output": "", - "status": "curated", + "id": "ks-06b21ad349", + "week": 4, + "source": "materials/post_midterm/Lecture Week 4.pptx", + "source_type": "lecture", + "topic": "OOP Fundamentals", + "subtopic_id": "w4-oop-fundamentals-core", + "subtopic_title": "Class Definition, __init__, self, and Attribute Basics", + "title": "Class Definition and __init__", + "explanation": "A class is a blueprint. The __init__ method is the constructor called automatically when a new object is created to initialize attributes.", + "code_examples": [ + { + "description": "Defining a simple class", + "code": "class Car:\n def __init__(self, color):\n self.color = color" + } + ] + }, + { + "id": "ks-9e278d1ee6", + "week": 4, + "source": "materials/post_midterm/Lecture Week 4.pptx", + "source_type": "lecture", + "topic": "OOP Fundamentals", + "subtopic_id": "w4-oop-fundamentals-core", + "subtopic_title": "Class Definition, __init__, self, and Attribute Basics", + "title": "The self Parameter", + "explanation": "In class methods, 'self' refers to the specific instance of the object. It must be the first parameter of any instance method.", + "code_examples": [ + { + "description": "Using self to access attributes", + "code": "class Dog:\n def __init__(self, name):\n self.name = name\n def bark(self):\n return f'{self.name} says woof!'" + } + ] + }, + { + "id": "ks-5cbba26b09", + "week": 4, + "source": "materials/post_midterm/Lecture Week 4.pptx", + "source_type": "lecture", + "topic": "OOP Fundamentals", + "subtopic_id": "w4-oop-fundamentals-core", + "subtopic_title": "Class Definition, __init__, self, and Attribute Basics", + "title": "Class vs Instance Attributes", + "explanation": "Instance attributes (self.x) are unique to each object. Class attributes are defined outside methods and shared by all instances of the class.", + "code_examples": [ + { + "description": "Shared class attribute", + "code": "class Counter:\n count = 0\n def __init__(self):\n Counter.count += 1" + } + ] + } + ], + "notebook_snippets": [ + { + "id": "cs-0d319e4faf", + "week": 4, + "cell_index": null, + "cell_type": "code", + "source_type": "notebook", + "topic": "OOP Fundamentals", + "subtopic_id": "w4-oop-fundamentals-core", + "subtopic_title": "Class Definition, __init__, self, and Attribute Basics", + "title": "class Rectangle:", + "source": "class Rectangle:\n total_size = 0\n def __init__(self, length, width=1):\n self.length = length\n self.width = width\n Rectangle.total_size += self.length * self.width\n print(f'{self.length} by {self.width} created, {Rectangle.total_size = }')\n def size(self, data_type=int):\n return f\"The size = {data_type(self.length * self.width)}.\"\n def __del__(self):\n Rectangle.total_size -= self.length * self.width\n print(f'{self.length} by {self.width} deleted, {Rectangle.total_size = }')\n \nprint(Rectangle.total_size)\nrectangle_1 = Rectangle(2,3) \nrectangle_2 = Rectangle(2)\ndel rectangle_1 \ndel rectangle_2", + "outputs": [ + "0\n2 by 3 created, Rectangle.total_size = 6\n2 by 1 created, Rectangle.total_size = 8\n2 by 3 deleted, Rectangle.total_size = 2\n2 by 1 deleted, Rectangle.total_size = 0" + ] + }, + { + "id": "cs-30e53467b8", + "week": 4, + "cell_index": null, + "cell_type": "code", + "source_type": "notebook", + "topic": "OOP Fundamentals", "subtopic_id": "w4-oop-fundamentals-core", - "subtopic_title": "Class Definition, __init__, self, and Attribute Basics" + "subtopic_title": "Class Definition, __init__, self, and Attribute Basics", + "title": "class Rectangle:", + "source": "class Rectangle:\n total_size = 0\n def __init__(self, length, width=1):\n self.length = length\n self.width = width\n Rectangle.total_size += self.length * self.width\n print(f'rectangle {self.length} by {self.width} created\\n{Rectangle.total_size = }')\n def size(self, data_type=int):\n return f\"The size = {data_type(self.length * self.width)}.\"\n def __del__(self):\n Rectangle.total_size -= self.length * self.width\n print(f'rectangle {self.length} by {self.width} deleted\\n{Rectangle.total_size = }')\n \nprint(Rectangle.total_size)\nrectangle_1 = Rectangle(2,3)\nrectangle_2 = Rectangle(3)\nrectangle_3 = Rectangle(2,2)\n\ndel rectangle_1\ndel rectangle_3\ndel rectangle_2", + "outputs": [ + "0\nrectangle 2 by 3 created\nRectangle.total_size = 6\nrectangle 3 by 1 created\nRectangle.total_size = 9\nrectangle 2 by 2 created\nRectangle.total_size = 13\nrectangle 2 by 3 deleted\nRectangle.total_size = 7\nrectangle 2 by 2 deleted\nRectangle.total_size = 3\nrectangle 3 by 1 deleted\nRectangle.total_size = 0" + ] }, { - "id": "ai-example-2", - "kind": "correct", - "title": "Using self to access attributes", - "code": "class Dog:\n def __init__(self, name):\n self.name = name\n def bark(self):\n return f'{self.name} says woof!'", - "why": "`self` refers to the current instance, so instance methods read and write data through `self.attr`.", - "output": "", - "status": "curated", + "id": "cs-e0dffaa52d", + "week": 4, + "cell_index": null, + "cell_type": "code", + "source_type": "notebook", + "topic": "OOP Fundamentals", "subtopic_id": "w4-oop-fundamentals-core", - "subtopic_title": "Class Definition, __init__, self, and Attribute Basics" + "subtopic_title": "Class Definition, __init__, self, and Attribute Basics", + "title": "class New_str(str):", + "source": "#\nclass New_str(str):\n def index(self, needle, start = 0):\n return self.find(needle, start)\n\na = New_str(\"abcd\")\nprint(a.upper()) \nprint(a.find(\"d\")) \nprint(a.find(\"e\")) \nprint(a.index(\"d\")) \nprint(a.index(\"e\"))", + "outputs": [] }, { - "id": "ai-example-3", - "kind": "correct", - "title": "Shared class attribute", - "code": "class Counter:\n count = 0\n def __init__(self):\n Counter.count += 1", - "why": "`self.x` is per object; a class attribute is shared until an instance shadows it with its own value.", - "output": "", - "status": "curated", + "id": "cs-9bc6869c46", + "week": 4, + "cell_index": null, + "cell_type": "code", + "source_type": "notebook", + "topic": "OOP Fundamentals", "subtopic_id": "w4-oop-fundamentals-core", - "subtopic_title": "Class Definition, __init__, self, and Attribute Basics" + "subtopic_title": "Class Definition, __init__, self, and Attribute Basics", + "title": "class Rectangle:", + "source": "#\nclass Rectangle:\n def __init__(self, length, width=1):\n self.length = length\n self.width = width\n def info_about_attribute_a(self):\n return f'{Rectangle.a=}, {self.a=}'\n\nrectangle_1 = Rectangle(2,3)\nRectangle.a = 5\nrectangle_1.a = 10\nprint(Rectangle.a, rectangle_1.a)\nprint(rectangle_1.info_about_attribute_a())", + "outputs": [] }, { - "id": "ai-example-6", - "kind": "correct", - "title": "Subclassing `str`", - "code": "#\nclass New_str(str):\n def index(self, needle, start = 0):\n return self.find(needle, start)\n\na = New_str(\"abcd\")\nprint(a.upper()) \nprint(a.find(\"d\")) \nprint(a.find(\"e\")) \nprint(a.index(\"d\")) \nprint(a.index(\"e\"))", - "why": "You can subclass a built-in type to add custom methods while keeping the original string behavior.", - "output": "", - "status": "curated", + "id": "cs-e76e122239", + "week": 4, + "cell_index": null, + "cell_type": "code", + "source_type": "notebook", + "topic": "OOP Fundamentals", "subtopic_id": "w4-oop-fundamentals-core", - "subtopic_title": "Class Definition, __init__, self, and Attribute Basics" + "subtopic_title": "Class Definition, __init__, self, and Attribute Basics", + "title": "class Rectangle:", + "source": "class Rectangle:\n def __init__(self, length, width=1):\n self.length = length\n self.width = width\n def size(self, data_type=int):\n return f\"The size = {data_type(self.length * self.width)}.\"\nrectangle_1 = Rectangle(2,3)\nrectangle_2 = Rectangle(3)\nrectangle_3 = Rectangle(2,2)\nfor object in [rectangle_1, rectangle_2, rectangle_3, Rectangle(4,4)]:\n print(object.size(float))", + "outputs": [] }, { - "id": "manual-oop-attrs", - "kind": "correct", - "title": "Class attribute vs instance attribute", - "code": "class Rectangle:\n units = 'cm'\n\n def __init__(self, width):\n self.width = width\n\nr1 = Rectangle(3)\nr2 = Rectangle(5)\nr2.units = 'm'\nprint(r1.units, r2.units)", - "output": "cm m", - "why": "`self.width` is per object; `Class.units` is shared until an instance shadows it with its own attribute.", - "status": "curated", + "id": "cs-040220fa7e", + "week": 4, + "cell_index": null, + "cell_type": "code", + "source_type": "notebook", + "topic": "OOP Fundamentals", "subtopic_id": "w4-oop-fundamentals-core", - "subtopic_title": "Class Definition, __init__, self, and Attribute Basics" + "subtopic_title": "Class Definition, __init__, self, and Attribute Basics", + "title": "class Rectangle:", + "source": "class Rectangle:\n def __init__(self, length, width=1):\n self.length = length\n self.width = width\n def size(self, data_type=int):\n return f\"The size = {data_type(self.length * self.width)}.\"\n \nrectangle_1 = Rectangle(2,3)\nrectangle_2 = Rectangle(3)\nrectangle_3 = Rectangle(2,2)\nfor object in [rectangle_1, rectangle_2, rectangle_3, Rectangle(4,4)]:\n print(Rectangle.size(object))", + "outputs": [] }, { - "id": "manual-oop-init-defaults", - "kind": "correct", - "title": "Safe default state in `__init__`", - "code": "class Book:\n def __init__(self, title, review_scores=None):\n self.title = title\n self.review_scores = [] if review_scores is None else review_scores", - "output": "", - "why": "Constructor defaults can make arguments optional, but mutable per-instance state should start from `None` and be created inside `__init__`.", - "status": "curated", + "id": "cs-f73de78062", + "week": 4, + "cell_index": null, + "cell_type": "code", + "source_type": "notebook", + "topic": "OOP Fundamentals", "subtopic_id": "w4-oop-fundamentals-core", - "subtopic_title": "Class Definition, __init__, self, and Attribute Basics" + "subtopic_title": "Class Definition, __init__, self, and Attribute Basics", + "title": "class Rectangle:", + "source": "class Rectangle:\n def __init__(self, length, width=1):\n self.length = length\n self.width = width\n def size(self, data_type=int):\n return f\"The size = {data_type(self.length * self.width)}.\"\n \nrectangle_1 = Rectangle(2,3)\nrectangle_2 = Rectangle(3)\nrectangle_3 = Rectangle(2,2)\n\nprint(rectangle_1.size())\nprint(rectangle_2.size(float))\nprint(rectangle_3.size(int))\nprint(Rectangle(4,4).size(str))", + "outputs": [] } ], "recommended_ids": [ - "exam-Test Exam 07-06-22-1-w4-oop-fundamentals", - "exam-Test Exam 07-06-22-2-w4-oop-fundamentals", + "exam-intro_python_sample_final_24_25-1-w5-pandas-core-structures", + "exam-intro_python_sample_final_24_25-2-w5-pandas-core-structures", "exam-Trial final exam Introduction to Python-1-w4-oop-fundamentals", + "exam-Test Exam 07-06-22-1-w4-oop-fundamentals", "exam-Trial final exam Introduction to Python-2-w4-oop-fundamentals", + "exam-Test Exam 07-06-22-2-w4-oop-fundamentals", "ks-06b21ad349", "ks-9e278d1ee6", "ks-5cbba26b09", "cs-0d319e4faf" - ] - } + ], + "homework_snippets": [], + "homework_recommended_ids": [] + }, + "subtopics": [ + { + "id": "w4-oop-fundamentals-core", + "item_ids": { + "exam_question_ids": [ + "exam-Test Exam 07-06-22-1-w4-oop-fundamentals", + "exam-Test Exam 07-06-22-2-w4-oop-fundamentals", + "exam-Trial final exam Introduction to Python-1-w4-oop-fundamentals", + "exam-Trial final exam Introduction to Python-2-w4-oop-fundamentals", + "exam-intro_python_sample_final_24_25-1-w5-pandas-core-structures", + "exam-intro_python_sample_final_24_25-2-w5-pandas-core-structures" + ], + "example_ids": [ + "ai-example-1", + "ai-example-2", + "ai-example-3", + "ai-example-6", + "manual-oop-constructor-defaults", + "manual-oop-state-compare", + "manual-oop-init-defaults", + "manual-oop-attrs" + ], + "key_point_ids": [ + "kp-1", + "kp-2", + "kp-3", + "kp-4", + "kp-manual-init-defaults" + ], + "lecture_snippet_ids": [ + "ks-06b21ad349", + "ks-9e278d1ee6", + "ks-5cbba26b09" + ], + "notebook_snippet_ids": [ + "cs-0d319e4faf", + "cs-30e53467b8", + "cs-e0dffaa52d", + "cs-9bc6869c46", + "cs-e76e122239", + "cs-040220fa7e", + "cs-f73de78062" + ] + }, + "order": 1, + "summary": "A class defines attributes and methods; `__init__` runs when you create an object and stores instance data on `self`.", + "title": "Class Definition, __init__, self, and Attribute Basics" + } + ], + "topic": "OOP Fundamentals", + "topic_meta": { + "week": 4, + "week_id": "week-4", + "week_title": "Week 4", + "topic_id": "w4-oop-fundamentals", + "topic_title": "OOP Fundamentals", + "topic_order": 4 + }, + "trap_patterns": [ + { + "pattern": "1 + True = 2 (bool is subclass of int)", + "trap": "True==1, False==0 in numeric contexts. type(True)==int is False but isinstance(True,int) is True", + "weeks": [ + 2 + ], + "appears_in_exams": [ + "midterm_2023" + ] + }, + { + "pattern": "for key in dict == for key in dict.keys()", + "trap": "Looping directly over a dict iterates over keys only", + "weeks": [ + 2 + ], + "appears_in_exams": [ + "midterm_2023" + ] + } + ], + "week_id": "week-4", + "weeks": [ + 4 + ] }, { "id": "w4-error-handling", @@ -11758,7 +12306,9 @@ "ks-40d373c410", "cs-e8bb5fd185", "cs-abb2b0f171" - ] + ], + "homework_snippets": [], + "homework_recommended_ids": [] } }, { @@ -11791,9 +12341,8 @@ ], "exam_question_ids": [ "exam-Test Exam 07-06-22-5-w5-pandas-core-structures", - "exam-intro_python_sample_final_24_25-1-w5-pandas-core-structures", - "exam-intro_python_sample_final_24_25-2-w5-pandas-core-structures", - "exam-Trial final exam Introduction to Python-5-w5-pandas-core-structures" + "exam-Trial final exam Introduction to Python-5-w5-pandas-core-structures", + "exam-intro_python_sample_final_24_25-5-w4-string-fundamentals" ], "notebook_snippet_ids": [ "cs-82ef14b9d5", @@ -11992,48 +12541,6 @@ "correct": "a", "explanation": "The map() method on a Series expects a function, dictionary, or another Series. If passed a Series, it uses the values of the caller (s) to look up indices in the passed Series. This will lead to unexpected results (looking up float values like 2.0 as indices) instead of applying the mathematical transformation. The other options correctly perform the element-wise operation." }, - { - "id": "exam-intro_python_sample_final_24_25-1-w5-pandas-core-structures", - "exam_label": "intro_python_sample_final_24_25", - "exam_source": "materials/post_midterm/Sample Final plus answers.pdf", - "year": "2024", - "number": 1, - "week": 5, - "topic": "OOP (Initializers)", - "subtopic_id": "w5-pandas-core-structures-core", - "subtopic_title": "Series, DataFrame, and Creation Patterns", - "question": "You'd like to define a class called Vehicle. It should have two attributes: name and mode, which you want to be initialized during object creation. The name attribute can be any string, and it must be passed to the object during creation. The mode attribute is also a string, but it doesn't necessarily need to be passed to the object constructor. If it isn't specified at object construction, then the mode attribute should be equal to the string \"land\". Which of the following code segments achieves what you want?", - "code_context": "my_car = Vehicle(\"Mazda\")\n# Expected: my_car.name == \"Mazda\" and my_car.mode == \"land\"", - "options": { - "A": "class Vehicle:\n def __init__(self, vehicle_name, vehicle_mode=\"land\"):\n self.name = vehicle_name\n self.mode = vehicle_mode", - "B": "class Vehicle:\n def __init__(self, vehicle_name, vehicle_mode):\n self.name = vehicle_name\n self.mode = vehicle_mode", - "C": "class Vehicle:\n def __init__(self, vehicle_name, vehicle_mode=\"land\"):\n return name, mode", - "D": "class Vehicle:\n def __init__(vehicle_name, vehicle_mode):\n name = vehicle_name\n mode = vehicle_mode" - }, - "correct": "A", - "explanation": "In Python, default parameter values in the __init__ method allow for optional arguments during object creation. Option A correctly assigns the parameters to instance attributes." - }, - { - "id": "exam-intro_python_sample_final_24_25-2-w5-pandas-core-structures", - "exam_label": "intro_python_sample_final_24_25", - "exam_source": "materials/post_midterm/Sample Final plus answers.pdf", - "year": "2024", - "number": 2, - "week": 5, - "topic": "OOP (Methods)", - "subtopic_id": "w5-pandas-core-structures-core", - "subtopic_title": "Series, DataFrame, and Creation Patterns", - "question": "Suppose that we create a Book object and call its add_review method three times, like this: book_1 = Book(\"The Lightning Thief\", \"Rick Riordan\"), book_1.add_review(5), book_1.add_review(3), book_1.add_review(3). What will then the following command print to the screen? print(book_1.show_rating())", - "code_context": "class Book:\n def __init__(self, title, author, review_scores=None):\n self.title = title\n self.author = author\n self.review_scores = review_scores if review_scores else []\n def add_review(self, score):\n self.review_scores.append(score)\n def show_rating(self):\n if self.review_scores:\n return round(sum(self.review_scores) / len(self.review_scores), 1)", - "options": { - "A": "3.7", - "B": "4", - "C": "None", - "D": "3.67" - }, - "correct": "A", - "explanation": "The average of scores [5, 3, 3] is 11 / 3 = 3.666... Using round(..., 1) results in 3.7." - }, { "id": "exam-Trial final exam Introduction to Python-5-w5-pandas-core-structures", "exam_label": "Trial final exam Introduction to Python", @@ -12054,6 +12561,27 @@ }, "correct": "a", "explanation": "Pandas supports vectorized operations. You can add two Series (columns) together element-wise by directly using the `+` operator." + }, + { + "id": "exam-intro_python_sample_final_24_25-5-w4-string-fundamentals", + "exam_label": "intro_python_sample_final_24_25", + "exam_source": "materials/post_midterm/Sample Final plus answers.pdf", + "year": "2024", + "number": 5, + "week": 5, + "topic": "Pandas (Basic)", + "subtopic_id": "w5-pandas-core-structures-core", + "subtopic_title": "Series, DataFrame, and Creation Patterns", + "question": "You have a pandas DataFrame called df with columns \"A\" and \"B\". You'd like to create a column called \"C\", which contains the sum of the numbers in columns \"A\" and \"B\". Which of the following code lines will achieve what you want?", + "code_context": "", + "options": { + "A": "df.loc[:,\"C\"] = df.loc[:,\"A\"] + df.loc[:,\"B\"]", + "B": "df.loc[\"c\"] = df.loc[\"A\"] + df.loc[\"B\"]", + "C": "df.loc[\"C\"] = df.loc[:,(\"A\" + \"B\")]", + "D": "df.loc[\"C\"] = df.loc[\"A\" + \"B\"]" + }, + "correct": "A", + "explanation": "Vectorized addition in Pandas is performed by adding series together. Using .loc[:, 'C'] correctly assigns the result to a new column for all rows." } ], "notebook_snippets": [ @@ -12312,15 +12840,16 @@ } ], "recommended_ids": [ + "exam-intro_python_sample_final_24_25-5-w4-string-fundamentals", "exam-Test Exam 07-06-22-5-w5-pandas-core-structures", - "exam-intro_python_sample_final_24_25-1-w5-pandas-core-structures", - "exam-intro_python_sample_final_24_25-2-w5-pandas-core-structures", "exam-Trial final exam Introduction to Python-5-w5-pandas-core-structures", "ks-052ed25923", "ks-9a5d2c05fb", "ks-75cf35c8b4", "cs-82ef14b9d5" - ] + ], + "homework_snippets": [], + "homework_recommended_ids": [] } }, { @@ -12354,7 +12883,8 @@ "ks-f550a3ffc7" ], "exam_question_ids": [ - "exam-Trial final exam Introduction to Python-6-w5-inspecting-and-selecting-data" + "exam-Trial final exam Introduction to Python-6-w5-inspecting-and-selecting-data", + "exam-intro_python_sample_final_24_25-6-w4-string-operations-and-methods" ], "notebook_snippet_ids": [ "cs-3d987070d4", @@ -12378,773 +12908,559 @@ ], "key_point_ids": [ "kp-1", - "kp-2", - "kp-3", - "kp-4", - "kp-5", - "kp-6" - ] - } - } - ], - "exam_stats": { - "total_hits": 1, - "by_exam": { - "Trial final exam Introduction to Python": 1 - }, - "coverage_count": 1 - }, - "related_topics": [ - "head, tail, describe, loc, iloc, Result Types, and Boolean Indexing" - ], - "trap_patterns": [ - { - "pattern": "UnboundLocalError", - "trap": "If a name appears on the left side of assignment ANYWHERE in a function, Python treats it as local THROUGHOUT the function body — even before the assignment line", - "weeks": [ - 3 - ], - "appears_in_exams": [ - "trial_midterm", - "extra_practice" - ] - } - ], - "sections": { - "lecture_snippets": [ - { - "id": "ks-0114a2cff0", - "week": 5, - "source": "materials/post_midterm/Lecture Week 5.pptx", - "source_type": "lecture", - "topic": "Inspecting and Selecting Data", - "subtopic_id": "w5-inspecting-and-selecting-data-core", - "subtopic_title": "head, tail, describe, loc, iloc, Result Types, and Boolean Indexing", - "title": "Viewing Data", - "explanation": "Use .head(n) for the first n rows, .tail(n) for the last n rows, and .describe() for summary statistics.", - "code_examples": [ - { - "description": "Summary stats", - "code": "print(df.describe())" - } - ] - }, - { - "id": "ks-57ff66f9f1", - "week": 5, - "source": "materials/post_midterm/Lecture Week 5.pptx", - "source_type": "lecture", - "topic": "Inspecting and Selecting Data", - "subtopic_id": "w5-inspecting-and-selecting-data-core", - "subtopic_title": "head, tail, describe, loc, iloc, Result Types, and Boolean Indexing", - "title": "Selection: loc", - "explanation": "Label-based selection. Slicing with .loc is inclusive of the end name.", - "code_examples": [ - { - "description": "Select rows/cols by name", - "code": "df.loc['First':'Third', ['Name', 'Weight']]" - } - ] - }, - { - "id": "ks-dfc064979d", - "week": 5, - "source": "materials/post_midterm/Lecture Week 5.pptx", - "source_type": "lecture", - "topic": "Inspecting and Selecting Data", - "subtopic_id": "w5-inspecting-and-selecting-data-core", - "subtopic_title": "head, tail, describe, loc, iloc, Result Types, and Boolean Indexing", - "title": "Selection: iloc", - "explanation": "Integer-position based selection. Slicing with .iloc is exclusive of the end index (like standard Python lists).", - "code_examples": [ - { - "description": "Select by position", - "code": "df.iloc[0:2, 0:1] # Rows 0,1; Col 0" - } - ] - }, - { - "id": "ks-99fe849762", - "week": 5, - "source": "materials/post_midterm/Lecture Week 5.pptx", - "source_type": "lecture", - "topic": "Inspecting and Selecting Data", - "subtopic_id": "w5-inspecting-and-selecting-data-core", - "subtopic_title": "head, tail, describe, loc, iloc, Result Types, and Boolean Indexing", - "title": "Selection Result Types", - "explanation": "Selecting a single row/column with a label returns a Series; using a list/slice returns a DataFrame.", - "code_examples": [ - { - "description": "Series vs DataFrame result", - "code": "type(df.loc[2]) # Series\ntype(df.loc[[2]]) # DataFrame" - } - ] - }, - { - "id": "ks-f550a3ffc7", - "week": 5, - "source": "materials/post_midterm/Lecture Week 5.pptx", - "source_type": "lecture", - "topic": "Inspecting and Selecting Data", - "subtopic_id": "w5-inspecting-and-selecting-data-core", - "subtopic_title": "head, tail, describe, loc, iloc, Result Types, and Boolean Indexing", - "title": "Boolean Indexing", - "explanation": "Filtering data by passing a mask of True/False values (often created via comparisons).", - "code_examples": [ - { - "description": "Filter by condition", - "code": "df[df['Weight'] > 60]\ndf.loc[df.Age < 155]" - } - ] - } - ], - "exam_questions": [ - { - "id": "exam-Trial final exam Introduction to Python-6-w5-inspecting-and-selecting-data", - "exam_label": "Trial final exam Introduction to Python", - "exam_source": "materials/post_midterm/practice_exams_previous_years/trial-final-exam-solutions-introduction-to-python-3077951.pdf", - "year": "unknown", - "number": 6, - "week": 5, - "topic": "pandas", - "subtopic_id": "w5-inspecting-and-selecting-data-core", - "subtopic_title": "head, tail, describe, loc, iloc, Result Types, and Boolean Indexing", - "question": "You have a pandas DataFrame called df that looks like this, when printed:\n\n A B C D\n1 9.1 9.5 9.0 6.0\n2 6.4 8.2 7.5 1.7\n3 2.5 5.3 8.8 3.0\n4 6.7 3.6 7.2 6.9\n5 8.4 1.9 8.2 3.3\n6 8.1 8.4 9.9 2.2\n\nSuppose that you'd like to create a new DataFrame that only contains those elements of column \"B\" in df that have an even-numbered index. Which of the following code lines will achieve what you want?", - "code_context": "", - "options": { - "a": "df.loc[df.index % 2 == 0, [\"B\"]]", - "b": "df[2, 4, 6, \"B\"]", - "c": "df.iloc[[2, 4, 6], 2]", - "d": "df.loc[2::2, \"B\"]" - }, - "correct": "a", - "explanation": "Option A uses boolean indexing (`df.index % 2 == 0`) to select rows with even index values, and specifically selects column \"B\" using `.loc`." - } - ], - "notebook_snippets": [ - { - "id": "cs-3d987070d4", - "week": 5, - "cell_index": null, - "cell_type": "code", - "source_type": "notebook", - "topic": "Inspecting and Selecting Data", - "subtopic_id": "w5-inspecting-and-selecting-data-core", - "subtopic_title": "head, tail, describe, loc, iloc, Result Types, and Boolean Indexing", - "title": "import pandas as pd", - "source": "import pandas as pd\nd1 = [['A', 'B', 'C'],[153, 160, 150],[55, 70, 60]]\ndf1 = pd.DataFrame (d1)\ndf1 = df1.drop(1, axis = 0)\ndf1 = df1.drop(1, axis = 1)\nprint(df1)\nresult = df1.iloc[2, 2]\nprint(result)\nprint(type(result))", - "outputs": [ - "0 2\n0 A C\n2 55 60" - ] - }, - { - "id": "cs-fb1645e573", - "week": 5, - "cell_index": null, - "cell_type": "code", - "source_type": "notebook", - "topic": "Inspecting and Selecting Data", - "subtopic_id": "w5-inspecting-and-selecting-data-core", - "subtopic_title": "head, tail, describe, loc, iloc, Result Types, and Boolean Indexing", - "title": "import pandas as pd", - "source": "import pandas as pd\nd1 = {10:['A', 'B', 'C', 'D'], 13:[153, 160, 150, 190], 12:[55, 70, 60, 80], 17:[10, 11, 12, 13]}\ndf1 = pd.DataFrame (d1, index=[3, 2, 1, 0])\nprint(df1)\n\nprint(df1.loc[df1.loc[:,13] < 155])\nprint(df1.loc[[3,1]])\nprint(df1.iloc[::2])", - "outputs": [] - }, - { - "id": "cs-2beee2b1ff", - "week": 5, - "cell_index": null, - "cell_type": "code", - "source_type": "notebook", - "topic": "Inspecting and Selecting Data", - "subtopic_id": "w5-inspecting-and-selecting-data-core", - "subtopic_title": "head, tail, describe, loc, iloc, Result Types, and Boolean Indexing", - "title": "import pandas as pd", - "source": "import pandas as pd\nd1 = {10:['A', 'B', 'C', 'D'], 13:[153, 160, 150, 190], 12:[55, 70, 60, 80], 17:[10, 11, 12, 13]}\ndf1 = pd.DataFrame (d1, index=[3, 2, 1, 0])\nprint(df1)\n\n\nprint(df1.loc[[True, True, False, False], [False, True, False, True]])\nprint(df1.loc[[True]*2 + [False]*2, [False, True]*2])\nprint(df1.loc[[3,2], [13, 17]])\nprint(df1.iloc[:2, [1, -1]])", - "outputs": [] - }, - { - "id": "cs-1506ef3ea9", - "week": 5, - "cell_index": null, - "cell_type": "code", - "source_type": "notebook", - "topic": "Inspecting and Selecting Data", - "subtopic_id": "w5-inspecting-and-selecting-data-core", - "subtopic_title": "head, tail, describe, loc, iloc, Result Types, and Boolean Indexing", - "title": "import pandas as pd", - "source": "import pandas as pd\nl1 = [11, 2, 3, 14, 5, 16, 7, 18, 29]\ns1 = pd.Series (l1)\ns1.index = range(3,30,3)\nprint(s1)\n\nprint(s1.loc[15])\nprint(s1.iloc[4])\n\nprint(s1.loc[:15])\nprint(s1.iloc[:4])\n\nprint(s1.loc[15])\nprint(s1.loc[[True, True, True, True, True, True, False, False, False]])", - "outputs": [] - }, - { - "id": "cs-67eb900ae2", - "week": 5, - "cell_index": null, - "cell_type": "code", - "source_type": "notebook", - "topic": "Inspecting and Selecting Data", - "subtopic_id": "w5-inspecting-and-selecting-data-core", - "subtopic_title": "head, tail, describe, loc, iloc, Result Types, and Boolean Indexing", - "title": "import pandas as pd", - "source": "import pandas as pd\nd1 = {10:['A', 'B', 'C', 'D'], 13:[153, 160, 150, 190], 12:[55, 70, 60, 80], 17:[10, 11, 12, 13]}\ndf1 = pd.DataFrame (d1, index=[3, 2, 1, 0])\nprint(df1)\n\nresult = df1.loc[[2]]\nprint(result)\nprint(type(result))\n\nresult = df1.iloc[[1]]\nprint(result)\nprint(type(result))", - "outputs": [] - }, - { - "id": "cs-0b913479b1", - "week": 5, - "cell_index": null, - "cell_type": "code", - "source_type": "notebook", - "topic": "Inspecting and Selecting Data", - "subtopic_id": "w5-inspecting-and-selecting-data-core", - "subtopic_title": "head, tail, describe, loc, iloc, Result Types, and Boolean Indexing", - "title": "import pandas as pd", - "source": "import pandas as pd\nd1 = {10:['A', 'B', 'C', 'D'], 13:[153, 160, 150, 190], 12:[55, 70, 60, 80], 17:[10, 11, 12, 13]}\ndf1 = pd.DataFrame (d1, index=[3, 2, 1, 0])\nprint(df1)\n\nresult = df1.loc[:, :]\nprint(result)\nprint(type(result))\n\nresult = df1.iloc[:, :]\nprint(result)\nprint(type(result))", - "outputs": [] - }, - { - "id": "cs-63b6c8f377", - "week": 5, - "cell_index": null, - "cell_type": "code", - "source_type": "notebook", - "topic": "Inspecting and Selecting Data", - "subtopic_id": "w5-inspecting-and-selecting-data-core", - "subtopic_title": "head, tail, describe, loc, iloc, Result Types, and Boolean Indexing", - "title": "import pandas as pd", - "source": "import pandas as pd\nd1 = {10:['A', 'B', 'C', 'D'], 13:[153, 160, 150, 190], 12:[55, 70, 60, 80], 17:[10, 11, 12, 13]}\ndf1 = pd.DataFrame (d1, index=[3, 2, 1, 0])\nprint(df1)\n\nresult = df1.loc[2,13]\nprint(result)\nprint(type(result))\n\nresult = df1.iloc[-3,1]\nprint(result)\nprint(type(result))", - "outputs": [] - }, - { - "id": "cs-185498320d", - "week": 5, - "cell_index": null, - "cell_type": "code", - "source_type": "notebook", - "topic": "Inspecting and Selecting Data", - "subtopic_id": "w5-inspecting-and-selecting-data-core", - "subtopic_title": "head, tail, describe, loc, iloc, Result Types, and Boolean Indexing", - "title": "import pandas as pd", - "source": "import pandas as pd\nd1 = {10:['A', 'B', 'C', 'D'], 13:[153, 160, 150, 190], 12:[55, 70, 60, 80], 17:[10, 11, 12, 13]}\ndf1 = pd.DataFrame (d1, index=[3, 2, 1, 0])\nprint(df1)\n\nresult = df1.loc[[3, 0]]\nprint(result)\nprint(type(result))\n\nresult = df1.iloc[[0,3]]\nprint(result)\nprint(type(result))", - "outputs": [] + "kp-2", + "kp-3", + "kp-4", + "kp-5", + "kp-6" + ] } - ], - "ai_summary": { - "status": "curated", - "content": "Use `head`, `tail`, and `describe` to inspect quickly. Use `.loc` for labels, `.iloc` for integer positions, and boolean masks for row filtering.", - "generator": "lecture-first-build", - "model": null + } + ], + "exam_stats": { + "total_hits": 1, + "by_exam": { + "Trial final exam Introduction to Python": 1 }, - "ai_common_questions": { - "status": "curated", - "bullets": [ - "You have a pandas DataFrame called df that looks like this, when printed:\n\n A B C D\n1 9.1 9.5 9.0 6.0\n2 6.4 8.2 7.5 1.7\n3 2.5 5.3 8.8 3.0\n4 6.7 3.6 7.2 6.9\n5 8.4 1.9 8.2 3.3\n6 8.1 8.4 9.9 2.2\n\nSuppose that you'd like to c…", - "If a name appears on the left side of assignment ANYWHERE in a function, Python treats it as local THROUGHOUT the function body — even before the assignment line" - ], - "items": [ - { - "id": "aiq-1", - "summary": "What happens if you run print(df.iloc[5, 2]) on a DataFrame with only 3 rows?", - "detail": "Unlike slicing, accessing a specific single position with .iloc that is out of bounds raises an IndexError.", - "extra": "Selection with iloc", - "subtopic_id": "w5-inspecting-and-selecting-data-core", - "subtopic_title": "head, tail, describe, loc, iloc, Result Types, and Boolean Indexing" - }, - { - "id": "aiq-5", - "summary": "UnboundLocalError", - "detail": "If a name appears on the left side of assignment ANYWHERE in a function, Python treats it as local THROUGHOUT the function body — even before the assignment line", - "extra": "", - "subtopic_id": "", - "subtopic_title": "" - } + "coverage_count": 1 + }, + "related_topics": [ + "head, tail, describe, loc, iloc, Result Types, and Boolean Indexing" + ], + "trap_patterns": [ + { + "pattern": "UnboundLocalError", + "trap": "If a name appears on the left side of assignment ANYWHERE in a function, Python treats it as local THROUGHOUT the function body — even before the assignment line", + "weeks": [ + 3 ], - "generator": "lecture-first-build", - "model": null - }, - "key_points_to_remember": [ + "appears_in_exams": [ + "trial_midterm", + "extra_practice" + ] + } + ], + "sections": { + "lecture_snippets": [ { - "id": "kp-1", - "text": "Use .head(n) for the first n rows, .tail(n) for the last n rows, and .describe() for summary statistics.", - "status": "curated", - "generator": "lecture-first-build", - "model": null, + "id": "ks-0114a2cff0", + "week": 5, + "source": "materials/post_midterm/Lecture Week 5.pptx", + "source_type": "lecture", + "topic": "Inspecting and Selecting Data", "subtopic_id": "w5-inspecting-and-selecting-data-core", "subtopic_title": "head, tail, describe, loc, iloc, Result Types, and Boolean Indexing", - "details": [ + "title": "Viewing Data", + "explanation": "Use .head(n) for the first n rows, .tail(n) for the last n rows, and .describe() for summary statistics.", + "code_examples": [ { - "id": "kp-1-d1", - "kind": "example", - "title": "Summary stats", + "description": "Summary stats", "code": "print(df.describe())" - }, - { - "id": "kp-1-d2", - "kind": "table", - "title": "Dense reference table", - "table": { - "headers": [ - "Selector", - "What it uses", - "Result" - ], - "rows": [ - [ - "df.loc[row, col]", - "labels", - "endpoint-inclusive slicing" - ], - [ - "df.iloc[row, col]", - "positions", - "Python-style exclusive slice" - ], - [ - "df.head(n)", - "first rows", - "quick inspect" - ], - [ - "df[df['A'] > 0]", - "boolean filter", - "row subset" - ] - ] - } } ] }, { - "id": "kp-2", - "text": "Label-based selection. Slicing with .loc is inclusive of the end name.", - "status": "curated", - "generator": "lecture-first-build", - "model": null, + "id": "ks-57ff66f9f1", + "week": 5, + "source": "materials/post_midterm/Lecture Week 5.pptx", + "source_type": "lecture", + "topic": "Inspecting and Selecting Data", "subtopic_id": "w5-inspecting-and-selecting-data-core", "subtopic_title": "head, tail, describe, loc, iloc, Result Types, and Boolean Indexing", - "details": [ + "title": "Selection: loc", + "explanation": "Label-based selection. Slicing with .loc is inclusive of the end name.", + "code_examples": [ { - "id": "kp-2-d1", - "kind": "example", - "title": "Select rows/cols by name", + "description": "Select rows/cols by name", "code": "df.loc['First':'Third', ['Name', 'Weight']]" } ] }, { - "id": "kp-3", - "text": "Integer-position based selection. Slicing with .iloc is exclusive of the end index (like standard Python lists).", - "status": "curated", - "generator": "lecture-first-build", - "model": null, + "id": "ks-dfc064979d", + "week": 5, + "source": "materials/post_midterm/Lecture Week 5.pptx", + "source_type": "lecture", + "topic": "Inspecting and Selecting Data", "subtopic_id": "w5-inspecting-and-selecting-data-core", "subtopic_title": "head, tail, describe, loc, iloc, Result Types, and Boolean Indexing", - "details": [ + "title": "Selection: iloc", + "explanation": "Integer-position based selection. Slicing with .iloc is exclusive of the end index (like standard Python lists).", + "code_examples": [ { - "id": "kp-3-d1", - "kind": "example", - "title": "Select by position", + "description": "Select by position", "code": "df.iloc[0:2, 0:1] # Rows 0,1; Col 0" } ] }, { - "id": "kp-4", - "text": "Selecting a single row/column with a label returns a Series; using a list/slice returns a DataFrame.", - "status": "curated", - "generator": "lecture-first-build", - "model": null, + "id": "ks-99fe849762", + "week": 5, + "source": "materials/post_midterm/Lecture Week 5.pptx", + "source_type": "lecture", + "topic": "Inspecting and Selecting Data", "subtopic_id": "w5-inspecting-and-selecting-data-core", "subtopic_title": "head, tail, describe, loc, iloc, Result Types, and Boolean Indexing", - "details": [ + "title": "Selection Result Types", + "explanation": "Selecting a single row/column with a label returns a Series; using a list/slice returns a DataFrame.", + "code_examples": [ { - "id": "kp-4-d1", - "kind": "example", - "title": "Series vs DataFrame result", + "description": "Series vs DataFrame result", "code": "type(df.loc[2]) # Series\ntype(df.loc[[2]]) # DataFrame" } ] }, { - "id": "kp-5", - "text": "Filtering data by passing a mask of True/False values (often created via comparisons).", - "status": "curated", - "generator": "lecture-first-build", - "model": null, + "id": "ks-f550a3ffc7", + "week": 5, + "source": "materials/post_midterm/Lecture Week 5.pptx", + "source_type": "lecture", + "topic": "Inspecting and Selecting Data", "subtopic_id": "w5-inspecting-and-selecting-data-core", "subtopic_title": "head, tail, describe, loc, iloc, Result Types, and Boolean Indexing", - "details": [ + "title": "Boolean Indexing", + "explanation": "Filtering data by passing a mask of True/False values (often created via comparisons).", + "code_examples": [ { - "id": "kp-5-d1", - "kind": "example", - "title": "Filter by condition", + "description": "Filter by condition", "code": "df[df['Weight'] > 60]\ndf.loc[df.Age < 155]" } ] + } + ], + "exam_questions": [ + { + "id": "exam-Trial final exam Introduction to Python-6-w5-inspecting-and-selecting-data", + "exam_label": "Trial final exam Introduction to Python", + "exam_source": "materials/post_midterm/practice_exams_previous_years/trial-final-exam-solutions-introduction-to-python-3077951.pdf", + "year": "unknown", + "number": 6, + "week": 5, + "topic": "pandas", + "subtopic_id": "w5-inspecting-and-selecting-data-core", + "subtopic_title": "head, tail, describe, loc, iloc, Result Types, and Boolean Indexing", + "question": "You have a pandas DataFrame called df that looks like this, when printed:\n\n A B C D\n1 9.1 9.5 9.0 6.0\n2 6.4 8.2 7.5 1.7\n3 2.5 5.3 8.8 3.0\n4 6.7 3.6 7.2 6.9\n5 8.4 1.9 8.2 3.3\n6 8.1 8.4 9.9 2.2\n\nSuppose that you'd like to create a new DataFrame that only contains those elements of column \"B\" in df that have an even-numbered index. Which of the following code lines will achieve what you want?", + "code_context": "", + "options": { + "a": "df.loc[df.index % 2 == 0, [\"B\"]]", + "b": "df[2, 4, 6, \"B\"]", + "c": "df.iloc[[2, 4, 6], 2]", + "d": "df.loc[2::2, \"B\"]" + }, + "correct": "a", + "explanation": "Option A uses boolean indexing (`df.index % 2 == 0`) to select rows with even index values, and specifically selects column \"B\" using `.loc`." }, { - "id": "kp-6", - "text": "Pattern to remember: df.loc[df.index % 2 == 0, [\"B\"]]", - "status": "curated", - "generator": "lecture-first-build", - "model": null, + "id": "exam-intro_python_sample_final_24_25-6-w4-string-operations-and-methods", + "exam_label": "intro_python_sample_final_24_25", + "exam_source": "materials/post_midterm/Sample Final plus answers.pdf", + "year": "2024", + "number": 6, + "week": 5, + "topic": "Pandas (Indexing)", "subtopic_id": "w5-inspecting-and-selecting-data-core", "subtopic_title": "head, tail, describe, loc, iloc, Result Types, and Boolean Indexing", - "details": [] + "question": "Suppose that you'd like to create a new DataFrame that contains only column 'B' for rows with indices 2, 4, and 6. Which of the following code lines will achieve what you want?", + "code_context": "", + "options": { + "A": "df.loc[df.index % 2 == 0, [\"B\"]]", + "B": "df[2, 4, 6, \"B\"]", + "C": "df.iloc[[2, 4, 6], 2]", + "D": "df.loc[2::2, \"B\"]" + }, + "correct": "A", + "explanation": "Option A uses a boolean mask on the index to find even numbers and specifies ['B'] as a list to return a DataFrame. Option D would return a Series." } ], - "ai_examples": [ + "notebook_snippets": [ { - "id": "ai-example-1", - "kind": "correct", - "title": "Summary stats", - "code": "print(df.describe())", - "why": "Use .head(n) for the first n rows, .tail(n) for the last n rows, and .describe() for summary statistics.", - "output": "", - "status": "curated", + "id": "cs-3d987070d4", + "week": 5, + "cell_index": null, + "cell_type": "code", + "source_type": "notebook", + "topic": "Inspecting and Selecting Data", "subtopic_id": "w5-inspecting-and-selecting-data-core", - "subtopic_title": "head, tail, describe, loc, iloc, Result Types, and Boolean Indexing" + "subtopic_title": "head, tail, describe, loc, iloc, Result Types, and Boolean Indexing", + "title": "import pandas as pd", + "source": "import pandas as pd\nd1 = [['A', 'B', 'C'],[153, 160, 150],[55, 70, 60]]\ndf1 = pd.DataFrame (d1)\ndf1 = df1.drop(1, axis = 0)\ndf1 = df1.drop(1, axis = 1)\nprint(df1)\nresult = df1.iloc[2, 2]\nprint(result)\nprint(type(result))", + "outputs": [ + "0 2\n0 A C\n2 55 60" + ] }, { - "id": "ai-example-2", - "kind": "correct", - "title": "Select rows/cols by name", - "code": "df.loc['First':'Third', ['Name', 'Weight']]", - "why": "Label-based selection. Slicing with .loc is inclusive of the end name.", - "output": "", - "status": "curated", + "id": "cs-fb1645e573", + "week": 5, + "cell_index": null, + "cell_type": "code", + "source_type": "notebook", + "topic": "Inspecting and Selecting Data", "subtopic_id": "w5-inspecting-and-selecting-data-core", - "subtopic_title": "head, tail, describe, loc, iloc, Result Types, and Boolean Indexing" + "subtopic_title": "head, tail, describe, loc, iloc, Result Types, and Boolean Indexing", + "title": "import pandas as pd", + "source": "import pandas as pd\nd1 = {10:['A', 'B', 'C', 'D'], 13:[153, 160, 150, 190], 12:[55, 70, 60, 80], 17:[10, 11, 12, 13]}\ndf1 = pd.DataFrame (d1, index=[3, 2, 1, 0])\nprint(df1)\n\nprint(df1.loc[df1.loc[:,13] < 155])\nprint(df1.loc[[3,1]])\nprint(df1.iloc[::2])", + "outputs": [] }, { - "id": "ai-example-3", - "kind": "correct", - "title": "Select by position", - "code": "df.iloc[0:2, 0:1] # Rows 0,1; Col 0", - "why": "Integer-position based selection. Slicing with .iloc is exclusive of the end index (like standard Python lists).", - "output": "", - "status": "curated", + "id": "cs-2beee2b1ff", + "week": 5, + "cell_index": null, + "cell_type": "code", + "source_type": "notebook", + "topic": "Inspecting and Selecting Data", "subtopic_id": "w5-inspecting-and-selecting-data-core", - "subtopic_title": "head, tail, describe, loc, iloc, Result Types, and Boolean Indexing" + "subtopic_title": "head, tail, describe, loc, iloc, Result Types, and Boolean Indexing", + "title": "import pandas as pd", + "source": "import pandas as pd\nd1 = {10:['A', 'B', 'C', 'D'], 13:[153, 160, 150, 190], 12:[55, 70, 60, 80], 17:[10, 11, 12, 13]}\ndf1 = pd.DataFrame (d1, index=[3, 2, 1, 0])\nprint(df1)\n\n\nprint(df1.loc[[True, True, False, False], [False, True, False, True]])\nprint(df1.loc[[True]*2 + [False]*2, [False, True]*2])\nprint(df1.loc[[3,2], [13, 17]])\nprint(df1.iloc[:2, [1, -1]])", + "outputs": [] }, { - "id": "ai-example-4", - "kind": "correct", - "title": "Series vs DataFrame result", - "code": "type(df.loc[2]) # Series\ntype(df.loc[[2]]) # DataFrame", - "why": "Selecting a single row/column with a label returns a Series; using a list/slice returns a DataFrame.", - "output": "", - "status": "curated", + "id": "cs-1506ef3ea9", + "week": 5, + "cell_index": null, + "cell_type": "code", + "source_type": "notebook", + "topic": "Inspecting and Selecting Data", "subtopic_id": "w5-inspecting-and-selecting-data-core", - "subtopic_title": "head, tail, describe, loc, iloc, Result Types, and Boolean Indexing" + "subtopic_title": "head, tail, describe, loc, iloc, Result Types, and Boolean Indexing", + "title": "import pandas as pd", + "source": "import pandas as pd\nl1 = [11, 2, 3, 14, 5, 16, 7, 18, 29]\ns1 = pd.Series (l1)\ns1.index = range(3,30,3)\nprint(s1)\n\nprint(s1.loc[15])\nprint(s1.iloc[4])\n\nprint(s1.loc[:15])\nprint(s1.iloc[:4])\n\nprint(s1.loc[15])\nprint(s1.loc[[True, True, True, True, True, True, False, False, False]])", + "outputs": [] }, { - "id": "ai-example-5", - "kind": "correct", - "title": "Filter by condition", - "code": "df[df['Weight'] > 60]\ndf.loc[df.Age < 155]", - "why": "Filtering data by passing a mask of True/False values (often created via comparisons).", - "output": "", - "status": "curated", + "id": "cs-67eb900ae2", + "week": 5, + "cell_index": null, + "cell_type": "code", + "source_type": "notebook", + "topic": "Inspecting and Selecting Data", "subtopic_id": "w5-inspecting-and-selecting-data-core", - "subtopic_title": "head, tail, describe, loc, iloc, Result Types, and Boolean Indexing" + "subtopic_title": "head, tail, describe, loc, iloc, Result Types, and Boolean Indexing", + "title": "import pandas as pd", + "source": "import pandas as pd\nd1 = {10:['A', 'B', 'C', 'D'], 13:[153, 160, 150, 190], 12:[55, 70, 60, 80], 17:[10, 11, 12, 13]}\ndf1 = pd.DataFrame (d1, index=[3, 2, 1, 0])\nprint(df1)\n\nresult = df1.loc[[2]]\nprint(result)\nprint(type(result))\n\nresult = df1.iloc[[1]]\nprint(result)\nprint(type(result))", + "outputs": [] }, { - "id": "ai-example-6", - "kind": "correct", - "title": "import pandas as pd", - "code": "import pandas as pd\nd1 = [['A', 'B', 'C'],[153, 160, 150],[55, 70, 60]]\ndf1 = pd.DataFrame (d1)\ndf1 = df1.drop(1, axis = 0)\ndf1 = df1.drop(1, axis = 1)\nprint(df1)\nresult = df1.iloc[2, 2]\nprint(result)\nprint(type(result))", - "why": "Decide first whether the code is using labels (`.loc`) or integer positions (`.iloc`).", - "output": "0 2\n0 A C\n2 55 60", - "status": "curated", + "id": "cs-0b913479b1", + "week": 5, + "cell_index": null, + "cell_type": "code", + "source_type": "notebook", + "topic": "Inspecting and Selecting Data", "subtopic_id": "w5-inspecting-and-selecting-data-core", - "subtopic_title": "head, tail, describe, loc, iloc, Result Types, and Boolean Indexing" + "subtopic_title": "head, tail, describe, loc, iloc, Result Types, and Boolean Indexing", + "title": "import pandas as pd", + "source": "import pandas as pd\nd1 = {10:['A', 'B', 'C', 'D'], 13:[153, 160, 150, 190], 12:[55, 70, 60, 80], 17:[10, 11, 12, 13]}\ndf1 = pd.DataFrame (d1, index=[3, 2, 1, 0])\nprint(df1)\n\nresult = df1.loc[:, :]\nprint(result)\nprint(type(result))\n\nresult = df1.iloc[:, :]\nprint(result)\nprint(type(result))", + "outputs": [] }, { - "id": "ai-example-7", - "kind": "correct", - "title": "import pandas as pd", - "code": "import pandas as pd\nd1 = {10:['A', 'B', 'C', 'D'], 13:[153, 160, 150, 190], 12:[55, 70, 60, 80], 17:[10, 11, 12, 13]}\ndf1 = pd.DataFrame (d1, index=[3, 2, 1, 0])\nprint(df1)\n\nprint(df1.loc[df1.loc[:,13] < 155])\nprint(df1.loc[[3,1]])\nprint(df1.iloc[::2])", - "why": "Read the slice as `start:stop:step`; with a negative step Python walks right-to-left and still excludes the stop position.", - "output": "", - "status": "curated", + "id": "cs-63b6c8f377", + "week": 5, + "cell_index": null, + "cell_type": "code", + "source_type": "notebook", + "topic": "Inspecting and Selecting Data", "subtopic_id": "w5-inspecting-and-selecting-data-core", - "subtopic_title": "head, tail, describe, loc, iloc, Result Types, and Boolean Indexing" + "subtopic_title": "head, tail, describe, loc, iloc, Result Types, and Boolean Indexing", + "title": "import pandas as pd", + "source": "import pandas as pd\nd1 = {10:['A', 'B', 'C', 'D'], 13:[153, 160, 150, 190], 12:[55, 70, 60, 80], 17:[10, 11, 12, 13]}\ndf1 = pd.DataFrame (d1, index=[3, 2, 1, 0])\nprint(df1)\n\nresult = df1.loc[2,13]\nprint(result)\nprint(type(result))\n\nresult = df1.iloc[-3,1]\nprint(result)\nprint(type(result))", + "outputs": [] }, { - "id": "ai-example-8", - "kind": "correct", - "title": "import pandas as pd", - "code": "import pandas as pd\nd1 = {10:['A', 'B', 'C', 'D'], 13:[153, 160, 150, 190], 12:[55, 70, 60, 80], 17:[10, 11, 12, 13]}\ndf1 = pd.DataFrame (d1, index=[3, 2, 1, 0])\nprint(df1)\n\n\nprint(df1.loc[[True, True, False, False], [False, True, False, True]])\nprint(df1.loc[[True]*2 + [False]*2, [False, True]*2])\nprint(df1.loc[[3,2], [13, 17]])\nprint(df1.iloc[:2, [1, -1]])", - "why": "Use `.loc[:, column] = ...` when the assignment should fill or update an entire column by label.", - "output": "", - "status": "curated", + "id": "cs-185498320d", + "week": 5, + "cell_index": null, + "cell_type": "code", + "source_type": "notebook", + "topic": "Inspecting and Selecting Data", "subtopic_id": "w5-inspecting-and-selecting-data-core", - "subtopic_title": "head, tail, describe, loc, iloc, Result Types, and Boolean Indexing" + "subtopic_title": "head, tail, describe, loc, iloc, Result Types, and Boolean Indexing", + "title": "import pandas as pd", + "source": "import pandas as pd\nd1 = {10:['A', 'B', 'C', 'D'], 13:[153, 160, 150, 190], 12:[55, 70, 60, 80], 17:[10, 11, 12, 13]}\ndf1 = pd.DataFrame (d1, index=[3, 2, 1, 0])\nprint(df1)\n\nresult = df1.loc[[3, 0]]\nprint(result)\nprint(type(result))\n\nresult = df1.iloc[[0,3]]\nprint(result)\nprint(type(result))", + "outputs": [] } ], - "recommended_ids": [ - "exam-Trial final exam Introduction to Python-6-w5-inspecting-and-selecting-data", - "ks-0114a2cff0", - "ks-57ff66f9f1", - "ks-dfc064979d", - "ks-99fe849762", - "cs-3d987070d4", - "cs-fb1645e573", - "cs-2beee2b1ff" - ] - } - }, - { - "id": "w5-working-with-values", - "topic": "Working With Values", - "canonical_topic": "w5-working-with-values", - "weeks": [ - 5 - ], - "week_id": "week-5", - "topic_meta": { - "week": 5, - "week_id": "week-5", - "week_title": "Week 5", - "topic_id": "w5-working-with-values", - "topic_title": "Working With Values", - "topic_order": 3 - }, - "subtopics": [ - { - "id": "w5-working-with-values-core", - "title": "Sorting, Missing Data, Broadcasting, Vectorized Strings, isin, map, and apply", - "order": 1, - "summary": "Sort, fill or drop missing values, compare or broadcast columns, and apply vectorized string or Series methods. Prefer vectorized operations before row-wise `apply`.", - "item_ids": { - "lecture_snippet_ids": [ - "ks-305a41a33e", - "ks-f8eec928e1", - "ks-115ab52188", - "ks-2bed6c308f", - "ks-17e621a20d", - "ks-0d2d15f8d2", - "ks-18a9645168" - ], - "exam_question_ids": [], - "notebook_snippet_ids": [ - "cs-942bdc8228", - "cs-f46d5464f2" - ], - "example_ids": [ - "ai-example-1", - "ai-example-2", - "ai-example-3", - "ai-example-4", - "ai-example-5", - "ai-example-6", - "ai-example-7", - "ai-example-8", - "manual-working-values-string-vs-map", - "manual-working-values-axis-apply" - ], - "key_point_ids": [ - "kp-1", - "kp-2", - "kp-3", - "kp-4", - "kp-5", - "kp-6", - "kp-7", - "kp-manual-drop-missing" - ] - } - } - ], - "exam_stats": { - "total_hits": 0, - "by_exam": {}, - "coverage_count": 0 - }, - "related_topics": [ - "Sorting, Missing Data, Broadcasting, Vectorized Strings, isin, map, and apply" - ], - "trap_patterns": [ - { - "pattern": "map/filter return iterables, not lists", - "trap": "list(map(lambda x: x*2, l)) — must wrap in list(). Without it: ", - "weeks": [ - 3 - ], - "appears_in_exams": [ - "trial_midterm", - "extra_practice" - ] + "ai_summary": { + "status": "curated", + "content": "Use `head`, `tail`, and `describe` to inspect quickly. Use `.loc` for labels, `.iloc` for integer positions, and boolean masks for row filtering.", + "generator": "lecture-first-build", + "model": null }, - { - "pattern": "1 + True = 2 (bool is subclass of int)", - "trap": "True==1, False==0 in numeric contexts. type(True)==int is False but isinstance(True,int) is True", - "weeks": [ - 2 + "ai_common_questions": { + "status": "curated", + "bullets": [ + "You have a pandas DataFrame called df that looks like this, when printed:\n\n A B C D\n1 9.1 9.5 9.0 6.0\n2 6.4 8.2 7.5 1.7\n3 2.5 5.3 8.8 3.0\n4 6.7 3.6 7.2 6.9\n5 8.4 1.9 8.2 3.3\n6 8.1 8.4 9.9 2.2\n\nSuppose that you'd like to c…", + "If a name appears on the left side of assignment ANYWHERE in a function, Python treats it as local THROUGHOUT the function body — even before the assignment line" ], - "appears_in_exams": [ - "midterm_2023" - ] - } - ], - "sections": { - "lecture_snippets": [ + "items": [ + { + "id": "aiq-1", + "summary": "What happens if you run print(df.iloc[5, 2]) on a DataFrame with only 3 rows?", + "detail": "Unlike slicing, accessing a specific single position with .iloc that is out of bounds raises an IndexError.", + "extra": "Selection with iloc", + "subtopic_id": "w5-inspecting-and-selecting-data-core", + "subtopic_title": "head, tail, describe, loc, iloc, Result Types, and Boolean Indexing" + }, + { + "id": "aiq-5", + "summary": "UnboundLocalError", + "detail": "If a name appears on the left side of assignment ANYWHERE in a function, Python treats it as local THROUGHOUT the function body — even before the assignment line", + "extra": "", + "subtopic_id": "", + "subtopic_title": "" + } + ], + "generator": "lecture-first-build", + "model": null + }, + "key_points_to_remember": [ { - "id": "ks-305a41a33e", - "week": 5, - "source": "materials/post_midterm/Lecture Week 5.pptx", - "source_type": "lecture", - "topic": "Working With Values", - "subtopic_id": "w5-working-with-values-core", - "subtopic_title": "Sorting, Missing Data, Broadcasting, Vectorized Strings, isin, map, and apply", - "title": "Sorting", - "explanation": "Sort by labels with .sort_index() or by values with .sort_values(). axis=0 is rows, axis=1 is columns.", - "code_examples": [ + "id": "kp-1", + "text": "Use .head(n) for the first n rows, .tail(n) for the last n rows, and .describe() for summary statistics.", + "status": "curated", + "generator": "lecture-first-build", + "model": null, + "subtopic_id": "w5-inspecting-and-selecting-data-core", + "subtopic_title": "head, tail, describe, loc, iloc, Result Types, and Boolean Indexing", + "details": [ { - "description": "Sorting by column values", - "code": "df.sort_values(by='Length', ascending=False)" - } - ] - }, - { - "id": "ks-f8eec928e1", - "week": 5, - "source": "materials/post_midterm/Lecture Week 5.pptx", - "source_type": "lecture", - "topic": "Working With Values", - "subtopic_id": "w5-working-with-values-core", - "subtopic_title": "Sorting, Missing Data, Broadcasting, Vectorized Strings, isin, map, and apply", - "title": "Broadcasting", - "explanation": "Applying a scalar operation (like + or *) to an entire Series or DataFrame automatically.", - "code_examples": [ + "id": "kp-1-d1", + "kind": "example", + "title": "Summary stats", + "code": "print(df.describe())" + }, { - "description": "Scalar broadcasting", - "code": "df['Height'] += 10 # Adds 10 to every cell in the column" + "id": "kp-1-d2", + "kind": "table", + "title": "Dense reference table", + "table": { + "headers": [ + "Selector", + "What it uses", + "Result" + ], + "rows": [ + [ + "df.loc[row, col]", + "labels", + "endpoint-inclusive slicing" + ], + [ + "df.iloc[row, col]", + "positions", + "Python-style exclusive slice" + ], + [ + "df.head(n)", + "first rows", + "quick inspect" + ], + [ + "df[df['A'] > 0]", + "boolean filter", + "row subset" + ] + ] + } } ] }, { - "id": "ks-115ab52188", - "week": 5, - "source": "materials/post_midterm/Lecture Week 5.pptx", - "source_type": "lecture", - "topic": "Working With Values", - "subtopic_id": "w5-working-with-values-core", - "subtopic_title": "Sorting, Missing Data, Broadcasting, Vectorized Strings, isin, map, and apply", - "title": "Vectorized String Methods", - "explanation": "Accessible via .str, these allow string operations on every element of a Series.", - "code_examples": [ + "id": "kp-2", + "text": "Label-based selection. Slicing with .loc is inclusive of the end name.", + "status": "curated", + "generator": "lecture-first-build", + "model": null, + "subtopic_id": "w5-inspecting-and-selecting-data-core", + "subtopic_title": "head, tail, describe, loc, iloc, Result Types, and Boolean Indexing", + "details": [ { - "description": "Chained string operations", - "code": "s.str.upper().str.count('A')" + "id": "kp-2-d1", + "kind": "example", + "title": "Select rows/cols by name", + "code": "df.loc['First':'Third', ['Name', 'Weight']]" } ] }, { - "id": "ks-2bed6c308f", - "week": 5, - "source": "materials/post_midterm/Lecture Week 5.pptx", - "source_type": "lecture", - "topic": "Working With Values", - "subtopic_id": "w5-working-with-values-core", - "subtopic_title": "Sorting, Missing Data, Broadcasting, Vectorized Strings, isin, map, and apply", - "title": "isin()", - "explanation": "A vectorized version of 'in' to check if elements are within a collection.", - "code_examples": [ + "id": "kp-3", + "text": "Integer-position based selection. Slicing with .iloc is exclusive of the end index (like standard Python lists).", + "status": "curated", + "generator": "lecture-first-build", + "model": null, + "subtopic_id": "w5-inspecting-and-selecting-data-core", + "subtopic_title": "head, tail, describe, loc, iloc, Result Types, and Boolean Indexing", + "details": [ { - "description": "Filtering with isin", - "code": "vowels = list('aeiou')\ns[s.str[-1].str.lower().isin(vowels)]" + "id": "kp-3-d1", + "kind": "example", + "title": "Select by position", + "code": "df.iloc[0:2, 0:1] # Rows 0,1; Col 0" } ] }, { - "id": "ks-17e621a20d", - "week": 5, - "source": "materials/post_midterm/Lecture Week 5.pptx", - "source_type": "lecture", - "topic": "Working With Values", - "subtopic_id": "w5-working-with-values-core", - "subtopic_title": "Sorting, Missing Data, Broadcasting, Vectorized Strings, isin, map, and apply", - "title": "map()", - "explanation": "Applies a function (often a lambda) to every element of a Series.", - "code_examples": [ + "id": "kp-4", + "text": "Selecting a single row/column with a label returns a Series; using a list/slice returns a DataFrame.", + "status": "curated", + "generator": "lecture-first-build", + "model": null, + "subtopic_id": "w5-inspecting-and-selecting-data-core", + "subtopic_title": "head, tail, describe, loc, iloc, Result Types, and Boolean Indexing", + "details": [ { - "description": "Formatting with map", - "code": "df['W_g'] = df['Weight'].map(lambda x: f'{x*1000} g')" + "id": "kp-4-d1", + "kind": "example", + "title": "Series vs DataFrame result", + "code": "type(df.loc[2]) # Series\ntype(df.loc[[2]]) # DataFrame" } ] }, { - "id": "ks-0d2d15f8d2", - "week": 5, - "source": "materials/post_midterm/Lecture Week 5.pptx", - "source_type": "lecture", - "topic": "Working With Values", - "subtopic_id": "w5-working-with-values-core", - "subtopic_title": "Sorting, Missing Data, Broadcasting, Vectorized Strings, isin, map, and apply", - "title": "apply()", - "explanation": "Applies a function along an axis (0 for columns, 1 for rows) of a DataFrame.", - "code_examples": [ + "id": "kp-5", + "text": "Filtering data by passing a mask of True/False values (often created via comparisons).", + "status": "curated", + "generator": "lecture-first-build", + "model": null, + "subtopic_id": "w5-inspecting-and-selecting-data-core", + "subtopic_title": "head, tail, describe, loc, iloc, Result Types, and Boolean Indexing", + "details": [ { - "description": "Row-wise average", - "code": "df['Avg'] = df.apply(lambda x: x.mean(), axis=1)" + "id": "kp-5-d1", + "kind": "example", + "title": "Filter by condition", + "code": "df[df['Weight'] > 60]\ndf.loc[df.Age < 155]" } ] }, { - "id": "ks-18a9645168", - "week": 5, - "source": "materials/post_midterm/Lecture Week 5.pptx", - "source_type": "lecture", - "topic": "Working With Values", - "subtopic_id": "w5-working-with-values-core", - "subtopic_title": "Sorting, Missing Data, Broadcasting, Vectorized Strings, isin, map, and apply", - "title": "Missing Data", - "explanation": "Represented by np.nan. Use .isna() to detect and .fillna() to replace them.", - "code_examples": [ - { - "description": "Handling NaNs", - "code": "df.fillna('No value') # Replaces all NaNs" - } - ] + "id": "kp-6", + "text": "Pattern to remember: df.loc[df.index % 2 == 0, [\"B\"]]", + "status": "curated", + "generator": "lecture-first-build", + "model": null, + "subtopic_id": "w5-inspecting-and-selecting-data-core", + "subtopic_title": "head, tail, describe, loc, iloc, Result Types, and Boolean Indexing", + "details": [] } ], - "exam_questions": [], - "notebook_snippets": [ + "ai_examples": [ + { + "id": "ai-example-1", + "kind": "correct", + "title": "Summary stats", + "code": "print(df.describe())", + "why": "Use .head(n) for the first n rows, .tail(n) for the last n rows, and .describe() for summary statistics.", + "output": "", + "status": "curated", + "subtopic_id": "w5-inspecting-and-selecting-data-core", + "subtopic_title": "head, tail, describe, loc, iloc, Result Types, and Boolean Indexing" + }, + { + "id": "ai-example-2", + "kind": "correct", + "title": "Select rows/cols by name", + "code": "df.loc['First':'Third', ['Name', 'Weight']]", + "why": "Label-based selection. Slicing with .loc is inclusive of the end name.", + "output": "", + "status": "curated", + "subtopic_id": "w5-inspecting-and-selecting-data-core", + "subtopic_title": "head, tail, describe, loc, iloc, Result Types, and Boolean Indexing" + }, + { + "id": "ai-example-3", + "kind": "correct", + "title": "Select by position", + "code": "df.iloc[0:2, 0:1] # Rows 0,1; Col 0", + "why": "Integer-position based selection. Slicing with .iloc is exclusive of the end index (like standard Python lists).", + "output": "", + "status": "curated", + "subtopic_id": "w5-inspecting-and-selecting-data-core", + "subtopic_title": "head, tail, describe, loc, iloc, Result Types, and Boolean Indexing" + }, + { + "id": "ai-example-4", + "kind": "correct", + "title": "Series vs DataFrame result", + "code": "type(df.loc[2]) # Series\ntype(df.loc[[2]]) # DataFrame", + "why": "Selecting a single row/column with a label returns a Series; using a list/slice returns a DataFrame.", + "output": "", + "status": "curated", + "subtopic_id": "w5-inspecting-and-selecting-data-core", + "subtopic_title": "head, tail, describe, loc, iloc, Result Types, and Boolean Indexing" + }, + { + "id": "ai-example-5", + "kind": "correct", + "title": "Filter by condition", + "code": "df[df['Weight'] > 60]\ndf.loc[df.Age < 155]", + "why": "Filtering data by passing a mask of True/False values (often created via comparisons).", + "output": "", + "status": "curated", + "subtopic_id": "w5-inspecting-and-selecting-data-core", + "subtopic_title": "head, tail, describe, loc, iloc, Result Types, and Boolean Indexing" + }, { - "id": "cs-942bdc8228", - "week": 5, - "cell_index": null, - "cell_type": "code", - "source_type": "notebook", - "topic": "Working With Values", - "subtopic_id": "w5-working-with-values-core", - "subtopic_title": "Sorting, Missing Data, Broadcasting, Vectorized Strings, isin, map, and apply", + "id": "ai-example-6", + "kind": "correct", "title": "import pandas as pd", - "source": "import pandas as pd\nd1 = {'A':[2, 5, 6], 'B':[3, 4, 7]}\ndf1 = pd.DataFrame (d1)\nprint(df1)\n\ndf2 = df1.loc[:]\ndf2 = df2.applymap(lambda x: 3 * x)\nprint(df2)", - "outputs": [] + "code": "import pandas as pd\nd1 = [['A', 'B', 'C'],[153, 160, 150],[55, 70, 60]]\ndf1 = pd.DataFrame (d1)\ndf1 = df1.drop(1, axis = 0)\ndf1 = df1.drop(1, axis = 1)\nprint(df1)\nresult = df1.iloc[2, 2]\nprint(result)\nprint(type(result))", + "why": "Decide first whether the code is using labels (`.loc`) or integer positions (`.iloc`).", + "output": "0 2\n0 A C\n2 55 60", + "status": "curated", + "subtopic_id": "w5-inspecting-and-selecting-data-core", + "subtopic_title": "head, tail, describe, loc, iloc, Result Types, and Boolean Indexing" }, { - "id": "cs-f46d5464f2", - "week": 5, - "cell_index": null, - "cell_type": "code", - "source_type": "notebook", - "topic": "Working With Values", - "subtopic_id": "w5-working-with-values-core", - "subtopic_title": "Sorting, Missing Data, Broadcasting, Vectorized Strings, isin, map, and apply", + "id": "ai-example-7", + "kind": "correct", "title": "import pandas as pd", - "source": "import pandas as pd\ns1 = pd.Series(list('Python'))\nprint(s1)\n\nprint(s1.map(lambda x: x.lower() in 'aeiou'))\nprint(s1.str.lower().isin(list('aeiou')))\nprint(s1[s1.str.lower().isin(list('aeiou'))])\n\nprint(s1.map(lambda x: x.lower() not in 'aeiou'))\nprint(~s1.str.lower().isin(list('aeiou')))\nprint(s1[~s1.str.lower().isin(list('aeiou'))])", - "outputs": [] + "code": "import pandas as pd\nd1 = {10:['A', 'B', 'C', 'D'], 13:[153, 160, 150, 190], 12:[55, 70, 60, 80], 17:[10, 11, 12, 13]}\ndf1 = pd.DataFrame (d1, index=[3, 2, 1, 0])\nprint(df1)\n\nprint(df1.loc[df1.loc[:,13] < 155])\nprint(df1.loc[[3,1]])\nprint(df1.iloc[::2])", + "why": "Read the slice as `start:stop:step`; with a negative step Python walks right-to-left and still excludes the stop position.", + "output": "", + "status": "curated", + "subtopic_id": "w5-inspecting-and-selecting-data-core", + "subtopic_title": "head, tail, describe, loc, iloc, Result Types, and Boolean Indexing" + }, + { + "id": "ai-example-8", + "kind": "correct", + "title": "import pandas as pd", + "code": "import pandas as pd\nd1 = {10:['A', 'B', 'C', 'D'], 13:[153, 160, 150, 190], 12:[55, 70, 60, 80], 17:[10, 11, 12, 13]}\ndf1 = pd.DataFrame (d1, index=[3, 2, 1, 0])\nprint(df1)\n\n\nprint(df1.loc[[True, True, False, False], [False, True, False, True]])\nprint(df1.loc[[True]*2 + [False]*2, [False, True]*2])\nprint(df1.loc[[3,2], [13, 17]])\nprint(df1.iloc[:2, [1, -1]])", + "why": "Use `.loc[:, column] = ...` when the assignment should fill or update an entire column by label.", + "output": "", + "status": "curated", + "subtopic_id": "w5-inspecting-and-selecting-data-core", + "subtopic_title": "head, tail, describe, loc, iloc, Result Types, and Boolean Indexing" } ], - "ai_summary": { - "status": "curated", - "content": "Sort, fill or drop missing values, compare or broadcast columns, and apply vectorized string or Series methods. Prefer vectorized operations before row-wise `apply`.", - "generator": "lecture-first-build", - "model": null - }, + "recommended_ids": [ + "exam-intro_python_sample_final_24_25-6-w4-string-operations-and-methods", + "exam-Trial final exam Introduction to Python-6-w5-inspecting-and-selecting-data", + "ks-0114a2cff0", + "ks-57ff66f9f1", + "ks-dfc064979d", + "ks-99fe849762", + "cs-3d987070d4", + "cs-fb1645e573", + "cs-2beee2b1ff" + ], + "homework_snippets": [], + "homework_recommended_ids": [] + } + }, + { + "canonical_topic": "w5-working-with-values", + "exam_stats": { + "total_hits": 0, + "by_exam": {}, + "coverage_count": 0 + }, + "id": "w5-working-with-values", + "related_topics": [ + "Sorting, Missing Data, Broadcasting, Vectorized Strings, isin, map, and apply" + ], + "sections": { "ai_common_questions": { "status": "curated", "bullets": [ @@ -13176,18 +13492,202 @@ "subtopic_id": "", "subtopic_title": "" }, - { - "id": "aiq-4", - "summary": "1 + True = 2 (bool is subclass of int)", - "detail": "True==1, False==0 in numeric contexts. type(True)==int is False but isinstance(True,int) is True", - "extra": "", - "subtopic_id": "", - "subtopic_title": "" - } - ], - "generator": "lecture-first-build", - "model": null - }, + { + "id": "aiq-4", + "summary": "1 + True = 2 (bool is subclass of int)", + "detail": "True==1, False==0 in numeric contexts. type(True)==int is False but isinstance(True,int) is True", + "extra": "", + "subtopic_id": "", + "subtopic_title": "" + } + ], + "generator": "lecture-first-build", + "model": null + }, + "ai_examples": [ + { + "id": "ai-example-1", + "kind": "correct", + "title": "Sorting by column values", + "code": "df.sort_values(by='Length', ascending=False)", + "why": "Sort by labels with .sort_index() or by values with .sort_values(). axis=0 is rows, axis=1 is columns.", + "output": "", + "status": "curated", + "subtopic_id": "w5-working-with-values-core", + "subtopic_title": "Sorting, Missing Data, Broadcasting, Vectorized Strings, isin, map, and apply" + }, + { + "id": "ai-example-2", + "kind": "correct", + "title": "Scalar broadcasting", + "code": "df['Height'] += 10 # Adds 10 to every cell in the column", + "why": "Applying a scalar operation (like + or *) to an entire Series or DataFrame automatically.", + "output": "", + "status": "curated", + "subtopic_id": "w5-working-with-values-core", + "subtopic_title": "Sorting, Missing Data, Broadcasting, Vectorized Strings, isin, map, and apply" + }, + { + "id": "ai-example-3", + "kind": "correct", + "title": "Chained string operations", + "code": "s.str.upper().str.count('A')", + "why": "Accessible via .str, these allow string operations on every element of a Series.", + "output": "", + "status": "curated", + "subtopic_id": "w5-working-with-values-core", + "subtopic_title": "Sorting, Missing Data, Broadcasting, Vectorized Strings, isin, map, and apply" + }, + { + "id": "ai-example-4", + "kind": "correct", + "title": "Filtering with isin", + "code": "vowels = list('aeiou')\ns[s.str[-1].str.lower().isin(vowels)]", + "why": "A vectorized version of 'in' to check if elements are within a collection.", + "output": "", + "status": "curated", + "subtopic_id": "w5-working-with-values-core", + "subtopic_title": "Sorting, Missing Data, Broadcasting, Vectorized Strings, isin, map, and apply" + }, + { + "id": "ai-example-5", + "kind": "correct", + "title": "Formatting with map", + "code": "df['W_g'] = df['Weight'].map(lambda x: f'{x*1000} g')", + "why": "Applies a function (often a lambda) to every element of a Series.", + "output": "", + "status": "curated", + "subtopic_id": "w5-working-with-values-core", + "subtopic_title": "Sorting, Missing Data, Broadcasting, Vectorized Strings, isin, map, and apply" + }, + { + "id": "ai-example-6", + "kind": "correct", + "title": "Row-wise average", + "code": "df['Avg'] = df.apply(lambda x: x.mean(), axis=1)", + "why": "Applies a function along an axis (0 for columns, 1 for rows) of a DataFrame.", + "output": "", + "status": "curated", + "subtopic_id": "w5-working-with-values-core", + "subtopic_title": "Sorting, Missing Data, Broadcasting, Vectorized Strings, isin, map, and apply" + }, + { + "id": "manual-working-values-string-vs-map", + "kind": "correct", + "title": "`.str` methods vs `map(...)`", + "code": "s = pd.Series(['Aap', 'Nota', 'MIES'])\nprint(s.map(lambda x: x.lower()))\nprint(s.str.lower())", + "why": "Use `.str` for vectorized string operations; `map(...)` is useful when you need a custom per-value transformation.", + "output": "", + "status": "curated", + "subtopic_id": "w5-working-with-values-core", + "subtopic_title": "Sorting, Missing Data, Broadcasting, Vectorized Strings, isin, map, and apply" + }, + { + "id": "manual-working-values-axis-apply", + "kind": "correct", + "title": "`apply(axis=0)` vs `apply(axis=1)`", + "code": "df.loc['Av'] = df.apply(lambda x: x.mean(), axis=0)\ndf['Avg'] = df.apply(lambda x: x.mean(), axis=1)", + "why": "`axis=0` works column by column; `axis=1` works row by row.", + "output": "", + "status": "curated", + "subtopic_id": "w5-working-with-values-core", + "subtopic_title": "Sorting, Missing Data, Broadcasting, Vectorized Strings, isin, map, and apply" + }, + { + "id": "ai-example-7", + "kind": "correct", + "title": "Handling NaNs", + "code": "df.fillna('No value') # Replaces all NaNs", + "why": "Represented by np.nan. Use .isna() to detect and .fillna() to replace them.", + "output": "", + "status": "curated", + "subtopic_id": "w5-working-with-values-core", + "subtopic_title": "Sorting, Missing Data, Broadcasting, Vectorized Strings, isin, map, and apply" + }, + { + "id": "ai-example-8", + "kind": "correct", + "title": "import pandas as pd", + "code": "import pandas as pd\nd1 = {'A':[2, 5, 6], 'B':[3, 4, 7]}\ndf1 = pd.DataFrame (d1)\nprint(df1)\n\ndf2 = df1.loc[:]\ndf2 = df2.applymap(lambda x: 3 * x)\nprint(df2)", + "why": "Use `.loc[:, column] = ...` when the assignment should fill or update an entire column by label.", + "output": "", + "status": "curated", + "subtopic_id": "w5-working-with-values-core", + "subtopic_title": "Sorting, Missing Data, Broadcasting, Vectorized Strings, isin, map, and apply" + }, + { + "id": "manual-pandas-split-into-columns", + "kind": "correct", + "title": "Split string data into multiple DataFrame columns", + "code": "import pandas as pd\n\ndf = pd.DataFrame({\"place\": [\"Amsterdam; Noord-Holland\", \"Utrecht; Utrecht\"]})\ndf[[\"municipality\", \"province\"]] = df[\"place\"].str.split(\"; \", expand=True)\nprint(df)", + "output": " place municipality province\n0 Amsterdam; Noord-Holland Amsterdam Noord-Holland\n1 Utrecht; Utrecht Utrecht Utrecht", + "why": "Use `.str.split(..., expand=True)` when the exam wants one text column unpacked into multiple DataFrame columns.", + "status": "curated", + "subtopic_id": "w5-working-with-values-core", + "subtopic_title": "Sorting, Missing Data, Broadcasting, Vectorized Strings, isin, map, and apply" + }, + { + "id": "manual-pandas-map-column-sum", + "kind": "correct", + "title": "Trace `map(lambda x: x + df['B'].sum())`", + "code": "import pandas as pd\n\ndf = pd.DataFrame({\"A\": [1, 2], \"B\": [10, 20]})\nresult = df[\"A\"].map(lambda x: x + df[\"B\"].sum())\nprint(result.tolist())", + "output": "[31, 32]", + "why": "`df[\"B\"].sum()` is computed from the whole column, so each element from `A` gets the same total from `B` added to it.", + "status": "curated", + "subtopic_id": "w5-working-with-values-core", + "subtopic_title": "Sorting, Missing Data, Broadcasting, Vectorized Strings, isin, map, and apply" + } + ], + "ai_summary": { + "status": "curated", + "content": "Sort, fill or drop missing values, compare or broadcast columns, and apply vectorized string or Series methods. Prefer vectorized operations before row-wise `apply`.", + "generator": "lecture-first-build", + "model": null + }, + "exam_questions": [ + { + "id": "exam-intro_python_sample_final_24_25-7-w4-string-fundamentals", + "exam_label": "intro_python_sample_final_24_25", + "exam_source": "materials/post_midterm/Sample Final plus answers.pdf", + "year": "2024", + "number": 7, + "week": 5, + "topic": "Pandas (Subset/Sort)", + "subtopic_id": "w5-working-with-values-core", + "subtopic_title": "Sorting, Missing Data, Broadcasting, Vectorized Strings, isin, map, and apply", + "question": "Which of the following code lines could NOT have created df2 from df1?", + "code_context": "", + "options": { + "A": "df2 = df1.sort_index(ascending=False).loc[:,[\"A\", \"C\", \"D\"]]", + "B": "df2 = df1.iloc[[3, 2, 1], [0, 2, 3]]", + "C": "df2 = df1.loc[2:4, [\"A\", \"C\", \"D\"]].sort_values(\"D\", ascending=False)", + "D": "df2 = df1.loc[2:4, [\"A\", \"C\", \"D\"]].sort_values(\"C\")" + }, + "correct": "A", + "explanation": "Option A would sort all 5 rows of df1 and keep columns A, C, D, resulting in a 5-row DataFrame. df2 only has 3 rows (indices 4, 3, 2)." + }, + { + "id": "exam-intro_python_sample_final_24_25-8-w4-string-fundamentals", + "exam_label": "intro_python_sample_final_24_25", + "exam_source": "materials/post_midterm/Sample Final plus answers.pdf", + "year": "2024", + "number": 8, + "week": 5, + "topic": "Pandas (Series Strings)", + "subtopic_id": "w5-working-with-values-core", + "subtopic_title": "Sorting, Missing Data, Broadcasting, Vectorized Strings, isin, map, and apply", + "question": "You have a Series s with municipality and province names separated by \"; \". You'd like to create a new Series that only contains the municipality names. Which of the following code lines will achieve what you want?", + "code_context": "", + "options": { + "A": "s.map(lambda x: x.split(\"; \")[0])", + "B": "s.split(\"; \")[0]", + "C": "s.lambda(x.split(\"; \"))", + "D": "s.str[:9]" + }, + "correct": "A", + "explanation": "The .map() method allows applying a function (like splitting a string and taking the first part) to every element in a pandas Series." + } + ], "key_points_to_remember": [ { "id": "kp-1", @@ -13332,127 +13832,255 @@ ] } ], - "ai_examples": [ + "lecture_snippets": [ { - "id": "ai-example-1", - "kind": "correct", - "title": "Sorting by column values", - "code": "df.sort_values(by='Length', ascending=False)", - "why": "Sort by labels with .sort_index() or by values with .sort_values(). axis=0 is rows, axis=1 is columns.", - "output": "", - "status": "curated", + "id": "ks-305a41a33e", + "week": 5, + "source": "materials/post_midterm/Lecture Week 5.pptx", + "source_type": "lecture", + "topic": "Working With Values", "subtopic_id": "w5-working-with-values-core", - "subtopic_title": "Sorting, Missing Data, Broadcasting, Vectorized Strings, isin, map, and apply" + "subtopic_title": "Sorting, Missing Data, Broadcasting, Vectorized Strings, isin, map, and apply", + "title": "Sorting", + "explanation": "Sort by labels with .sort_index() or by values with .sort_values(). axis=0 is rows, axis=1 is columns.", + "code_examples": [ + { + "description": "Sorting by column values", + "code": "df.sort_values(by='Length', ascending=False)" + } + ] }, { - "id": "ai-example-2", - "kind": "correct", - "title": "Scalar broadcasting", - "code": "df['Height'] += 10 # Adds 10 to every cell in the column", - "why": "Applying a scalar operation (like + or *) to an entire Series or DataFrame automatically.", - "output": "", - "status": "curated", + "id": "ks-f8eec928e1", + "week": 5, + "source": "materials/post_midterm/Lecture Week 5.pptx", + "source_type": "lecture", + "topic": "Working With Values", "subtopic_id": "w5-working-with-values-core", - "subtopic_title": "Sorting, Missing Data, Broadcasting, Vectorized Strings, isin, map, and apply" + "subtopic_title": "Sorting, Missing Data, Broadcasting, Vectorized Strings, isin, map, and apply", + "title": "Broadcasting", + "explanation": "Applying a scalar operation (like + or *) to an entire Series or DataFrame automatically.", + "code_examples": [ + { + "description": "Scalar broadcasting", + "code": "df['Height'] += 10 # Adds 10 to every cell in the column" + } + ] }, { - "id": "ai-example-3", - "kind": "correct", - "title": "Chained string operations", - "code": "s.str.upper().str.count('A')", - "why": "Accessible via .str, these allow string operations on every element of a Series.", - "output": "", - "status": "curated", + "id": "ks-115ab52188", + "week": 5, + "source": "materials/post_midterm/Lecture Week 5.pptx", + "source_type": "lecture", + "topic": "Working With Values", "subtopic_id": "w5-working-with-values-core", - "subtopic_title": "Sorting, Missing Data, Broadcasting, Vectorized Strings, isin, map, and apply" + "subtopic_title": "Sorting, Missing Data, Broadcasting, Vectorized Strings, isin, map, and apply", + "title": "Vectorized String Methods", + "explanation": "Accessible via .str, these allow string operations on every element of a Series.", + "code_examples": [ + { + "description": "Chained string operations", + "code": "s.str.upper().str.count('A')" + } + ] }, { - "id": "ai-example-4", - "kind": "correct", - "title": "Filtering with isin", - "code": "vowels = list('aeiou')\ns[s.str[-1].str.lower().isin(vowels)]", - "why": "A vectorized version of 'in' to check if elements are within a collection.", - "output": "", - "status": "curated", + "id": "ks-2bed6c308f", + "week": 5, + "source": "materials/post_midterm/Lecture Week 5.pptx", + "source_type": "lecture", + "topic": "Working With Values", "subtopic_id": "w5-working-with-values-core", - "subtopic_title": "Sorting, Missing Data, Broadcasting, Vectorized Strings, isin, map, and apply" + "subtopic_title": "Sorting, Missing Data, Broadcasting, Vectorized Strings, isin, map, and apply", + "title": "isin()", + "explanation": "A vectorized version of 'in' to check if elements are within a collection.", + "code_examples": [ + { + "description": "Filtering with isin", + "code": "vowels = list('aeiou')\ns[s.str[-1].str.lower().isin(vowels)]" + } + ] }, { - "id": "ai-example-5", - "kind": "correct", - "title": "Formatting with map", - "code": "df['W_g'] = df['Weight'].map(lambda x: f'{x*1000} g')", - "why": "Applies a function (often a lambda) to every element of a Series.", - "output": "", - "status": "curated", + "id": "ks-17e621a20d", + "week": 5, + "source": "materials/post_midterm/Lecture Week 5.pptx", + "source_type": "lecture", + "topic": "Working With Values", "subtopic_id": "w5-working-with-values-core", - "subtopic_title": "Sorting, Missing Data, Broadcasting, Vectorized Strings, isin, map, and apply" + "subtopic_title": "Sorting, Missing Data, Broadcasting, Vectorized Strings, isin, map, and apply", + "title": "map()", + "explanation": "Applies a function (often a lambda) to every element of a Series.", + "code_examples": [ + { + "description": "Formatting with map", + "code": "df['W_g'] = df['Weight'].map(lambda x: f'{x*1000} g')" + } + ] }, { - "id": "ai-example-6", - "kind": "correct", - "title": "Row-wise average", - "code": "df['Avg'] = df.apply(lambda x: x.mean(), axis=1)", - "why": "Applies a function along an axis (0 for columns, 1 for rows) of a DataFrame.", - "output": "", - "status": "curated", + "id": "ks-0d2d15f8d2", + "week": 5, + "source": "materials/post_midterm/Lecture Week 5.pptx", + "source_type": "lecture", + "topic": "Working With Values", "subtopic_id": "w5-working-with-values-core", - "subtopic_title": "Sorting, Missing Data, Broadcasting, Vectorized Strings, isin, map, and apply" + "subtopic_title": "Sorting, Missing Data, Broadcasting, Vectorized Strings, isin, map, and apply", + "title": "apply()", + "explanation": "Applies a function along an axis (0 for columns, 1 for rows) of a DataFrame.", + "code_examples": [ + { + "description": "Row-wise average", + "code": "df['Avg'] = df.apply(lambda x: x.mean(), axis=1)" + } + ] }, { - "id": "manual-working-values-string-vs-map", - "kind": "correct", - "title": "`.str` methods vs `map(...)`", - "code": "s = pd.Series(['Aap', 'Nota', 'MIES'])\nprint(s.map(lambda x: x.lower()))\nprint(s.str.lower())", - "why": "Use `.str` for vectorized string operations; `map(...)` is useful when you need a custom per-value transformation.", - "output": "", - "status": "curated", + "id": "ks-18a9645168", + "week": 5, + "source": "materials/post_midterm/Lecture Week 5.pptx", + "source_type": "lecture", + "topic": "Working With Values", "subtopic_id": "w5-working-with-values-core", - "subtopic_title": "Sorting, Missing Data, Broadcasting, Vectorized Strings, isin, map, and apply" - }, + "subtopic_title": "Sorting, Missing Data, Broadcasting, Vectorized Strings, isin, map, and apply", + "title": "Missing Data", + "explanation": "Represented by np.nan. Use .isna() to detect and .fillna() to replace them.", + "code_examples": [ + { + "description": "Handling NaNs", + "code": "df.fillna('No value') # Replaces all NaNs" + } + ] + } + ], + "notebook_snippets": [ { - "id": "manual-working-values-axis-apply", - "kind": "correct", - "title": "`apply(axis=0)` vs `apply(axis=1)`", - "code": "df.loc['Av'] = df.apply(lambda x: x.mean(), axis=0)\ndf['Avg'] = df.apply(lambda x: x.mean(), axis=1)", - "why": "`axis=0` works column by column; `axis=1` works row by row.", - "output": "", - "status": "curated", + "id": "cs-942bdc8228", + "week": 5, + "cell_index": null, + "cell_type": "code", + "source_type": "notebook", + "topic": "Working With Values", "subtopic_id": "w5-working-with-values-core", - "subtopic_title": "Sorting, Missing Data, Broadcasting, Vectorized Strings, isin, map, and apply" + "subtopic_title": "Sorting, Missing Data, Broadcasting, Vectorized Strings, isin, map, and apply", + "title": "import pandas as pd", + "source": "import pandas as pd\nd1 = {'A':[2, 5, 6], 'B':[3, 4, 7]}\ndf1 = pd.DataFrame (d1)\nprint(df1)\n\ndf2 = df1.loc[:]\ndf2 = df2.applymap(lambda x: 3 * x)\nprint(df2)", + "outputs": [] }, { - "id": "ai-example-7", - "kind": "correct", - "title": "Handling NaNs", - "code": "df.fillna('No value') # Replaces all NaNs", - "why": "Represented by np.nan. Use .isna() to detect and .fillna() to replace them.", - "output": "", - "status": "curated", + "id": "cs-f46d5464f2", + "week": 5, + "cell_index": null, + "cell_type": "code", + "source_type": "notebook", + "topic": "Working With Values", "subtopic_id": "w5-working-with-values-core", - "subtopic_title": "Sorting, Missing Data, Broadcasting, Vectorized Strings, isin, map, and apply" + "subtopic_title": "Sorting, Missing Data, Broadcasting, Vectorized Strings, isin, map, and apply", + "title": "import pandas as pd", + "source": "import pandas as pd\ns1 = pd.Series(list('Python'))\nprint(s1)\n\nprint(s1.map(lambda x: x.lower() in 'aeiou'))\nprint(s1.str.lower().isin(list('aeiou')))\nprint(s1[s1.str.lower().isin(list('aeiou'))])\n\nprint(s1.map(lambda x: x.lower() not in 'aeiou'))\nprint(~s1.str.lower().isin(list('aeiou')))\nprint(s1[~s1.str.lower().isin(list('aeiou'))])", + "outputs": [] + } + ], + "recommended_ids": [ + "exam-intro_python_sample_final_24_25-7-w4-string-fundamentals", + "exam-intro_python_sample_final_24_25-8-w4-string-fundamentals", + "ks-305a41a33e", + "ks-f8eec928e1", + "ks-115ab52188", + "ks-2bed6c308f", + "cs-942bdc8228", + "cs-f46d5464f2" + ], + "homework_snippets": [], + "homework_recommended_ids": [] + }, + "subtopics": [ + { + "id": "w5-working-with-values-core", + "item_ids": { + "exam_question_ids": [ + "exam-intro_python_sample_final_24_25-7-w4-string-fundamentals", + "exam-intro_python_sample_final_24_25-8-w4-string-fundamentals" + ], + "example_ids": [ + "ai-example-1", + "ai-example-2", + "ai-example-3", + "ai-example-4", + "ai-example-5", + "ai-example-6", + "ai-example-7", + "ai-example-8", + "manual-pandas-split-into-columns", + "manual-pandas-map-column-sum", + "manual-working-values-string-vs-map", + "manual-working-values-axis-apply" + ], + "key_point_ids": [ + "kp-1", + "kp-2", + "kp-3", + "kp-4", + "kp-5", + "kp-6", + "kp-7", + "kp-manual-drop-missing" + ], + "lecture_snippet_ids": [ + "ks-305a41a33e", + "ks-f8eec928e1", + "ks-115ab52188", + "ks-2bed6c308f", + "ks-17e621a20d", + "ks-0d2d15f8d2", + "ks-18a9645168" + ], + "notebook_snippet_ids": [ + "cs-942bdc8228", + "cs-f46d5464f2" + ] }, - { - "id": "ai-example-8", - "kind": "correct", - "title": "import pandas as pd", - "code": "import pandas as pd\nd1 = {'A':[2, 5, 6], 'B':[3, 4, 7]}\ndf1 = pd.DataFrame (d1)\nprint(df1)\n\ndf2 = df1.loc[:]\ndf2 = df2.applymap(lambda x: 3 * x)\nprint(df2)", - "why": "Use `.loc[:, column] = ...` when the assignment should fill or update an entire column by label.", - "output": "", - "status": "curated", - "subtopic_id": "w5-working-with-values-core", - "subtopic_title": "Sorting, Missing Data, Broadcasting, Vectorized Strings, isin, map, and apply" - } - ], - "recommended_ids": [ - "ks-305a41a33e", - "ks-f8eec928e1", - "ks-115ab52188", - "ks-2bed6c308f", - "cs-942bdc8228", - "cs-f46d5464f2" - ] - } + "order": 1, + "summary": "Sort, fill or drop missing values, compare or broadcast columns, and apply vectorized string or Series methods. Prefer vectorized operations before row-wise `apply`.", + "title": "Sorting, Missing Data, Broadcasting, Vectorized Strings, isin, map, and apply" + } + ], + "topic": "Working With Values", + "topic_meta": { + "week": 5, + "week_id": "week-5", + "week_title": "Week 5", + "topic_id": "w5-working-with-values", + "topic_title": "Working With Values", + "topic_order": 3 + }, + "trap_patterns": [ + { + "pattern": "map/filter return iterables, not lists", + "trap": "list(map(lambda x: x*2, l)) — must wrap in list(). Without it: ", + "weeks": [ + 3 + ], + "appears_in_exams": [ + "trial_midterm", + "extra_practice" + ] + }, + { + "pattern": "1 + True = 2 (bool is subclass of int)", + "trap": "True==1, False==0 in numeric contexts. type(True)==int is False but isinstance(True,int) is True", + "weeks": [ + 2 + ], + "appears_in_exams": [ + "midterm_2023" + ] + } + ], + "week_id": "week-5", + "weeks": [ + 5 + ] }, { "id": "w5-combining-data", @@ -13768,7 +14396,9 @@ "ks-f1be187b50", "cs-b46633d18d", "cs-9debea9604" - ] + ], + "homework_snippets": [], + "homework_recommended_ids": [] } }, { @@ -13804,7 +14434,9 @@ "ks-72c58bb6b2", "ks-dd2965ef50" ], - "exam_question_ids": [], + "exam_question_ids": [ + "exam-intro_python_sample_final_24_25-12-w2-conditions" + ], "notebook_snippet_ids": [ "cs-6a322e3274", "cs-5fc55f4102", @@ -14077,7 +14709,29 @@ ] } ], - "exam_questions": [], + "exam_questions": [ + { + "id": "exam-intro_python_sample_final_24_25-12-w2-conditions", + "exam_label": "intro_python_sample_final_24_25", + "exam_source": "materials/post_midterm/Sample Final plus answers.pdf", + "year": "2024", + "number": 12, + "week": 6, + "topic": "List Comprehensions", + "subtopic_id": "w6-comprehensions-core", + "subtopic_title": "List/Dict/Set Comprehensions, Nested Variants, Logic Filters, Walrus, and enumerate Patterns", + "question": "You'd like to turn every upper case letter in a list into lower case and vice versa. Which code line achieves this?", + "code_context": "", + "options": { + "A": "[letter.upper() if letter.islower() else letter.lower() for letter in list_1]", + "B": "[x if x in 'abcdefg...'.upper() else x.lower() for x in list_1]", + "C": "Both achieve what you want", + "D": "None achieves what you want" + }, + "correct": "C", + "explanation": "Both options implement the conditional logic required to flip the case of each character in the list." + } + ], "notebook_snippets": [ { "id": "cs-6a322e3274", @@ -14463,6 +15117,7 @@ } ], "recommended_ids": [ + "exam-intro_python_sample_final_24_25-12-w2-conditions", "ks-cacc4fbc21", "ks-0e5c8b8b42", "ks-3e04c4d5e8", @@ -14471,7 +15126,9 @@ "cs-5fc55f4102", "cs-f2be389e66", "cs-8162a05b72" - ] + ], + "homework_snippets": [], + "homework_recommended_ids": [] } }, { @@ -14804,140 +15461,281 @@ "why": "", "output": "", "status": "curated", - "subtopic_id": "w6-generators-and-iterators-core", - "subtopic_title": "Iterator Protocol, Generator Functions, and Generator Comprehensions" + "subtopic_id": "w6-generators-and-iterators-core", + "subtopic_title": "Iterator Protocol, Generator Functions, and Generator Comprehensions" + }, + { + "id": "ai-example-5", + "kind": "correct", + "title": "mygenerator = (x for x in range(100000000) if x%3 == 0 or x%4 == 0)", + "code": "mygenerator = (x for x in range(100000000) if x%3 == 0 or x%4 == 0)\nprint(next(mygenerator))\nprint(next(mygenerator))\nprint(next(mygenerator))\nprint(next(mygenerator))", + "why": "Expand `range(start, stop, step)` manually; `stop` is excluded and the next value is found by adding `step` each time.", + "output": "", + "status": "curated", + "subtopic_id": "w6-generators-and-iterators-core", + "subtopic_title": "Iterator Protocol, Generator Functions, and Generator Comprehensions" + }, + { + "id": "ai-example-6", + "kind": "correct", + "title": "class Mylist(list):", + "code": "class Mylist(list):\n def __iter__ (self):\n pass\nmyiterator = iter(Mylist([1,3,5]))\n\nprint(next(myiterator))\nprint(next(myiterator))\nprint(next(myiterator))\nprint(next(myiterator))", + "why": "", + "output": "", + "status": "curated", + "subtopic_id": "w6-generators-and-iterators-core", + "subtopic_title": "Iterator Protocol, Generator Functions, and Generator Comprehensions" + }, + { + "id": "ai-example-7", + "kind": "correct", + "title": "def generatorfunction(start, stop, step):", + "code": "def generatorfunction(start, stop, step):\n while (num:=start) <= stop:\n yield num\n start += step\n return 'End of numbers'\nfor x in generatorfunction(1, 5, 2):\n print(x)", + "why": "For numeric variables, `a += 1` updates the stored value the same way as `a = a + 1`.", + "output": "", + "status": "curated", + "subtopic_id": "w6-generators-and-iterators-core", + "subtopic_title": "Iterator Protocol, Generator Functions, and Generator Comprehensions" + }, + { + "id": "ai-example-8", + "kind": "correct", + "title": "def generatorfunction(start, stop, step):", + "code": "def generatorfunction(start, stop, step):\n while True:\n num = start\n start += step\n if num <= stop:\n yield num\n else:\n return 'End of numbers'\nprint(list(generatorfunction(1, 5, 2)))", + "why": "For numeric variables, `a += 1` updates the stored value the same way as `a = a + 1`.", + "output": "", + "status": "curated", + "subtopic_id": "w6-generators-and-iterators-core", + "subtopic_title": "Iterator Protocol, Generator Functions, and Generator Comprehensions" + } + ], + "recommended_ids": [ + "ks-900b394f8e", + "ks-cd030b9520", + "cs-0f95aa8463", + "cs-32bf0b7fdb", + "cs-078b563299", + "cs-a3d823b3c5" + ], + "homework_snippets": [], + "homework_recommended_ids": [] + } + }, + { + "canonical_topic": "w6-datetime", + "exam_stats": { + "total_hits": 2, + "by_exam": { + "intro_python_sample_final_24_25": 2 + }, + "coverage_count": 1 + }, + "id": "w6-datetime", + "related_topics": [ + "now, Timestamps, strftime, strptime, timedelta, and Date Arithmetic" + ], + "sections": { + "ai_common_questions": { + "status": "curated", + "bullets": [ + "Suppose that you call the function like this: get_months([\"03/02/2013\", \"03.02.2013\", \"03-02-2013\"]). What does the function call return?", + "Which of the following code segments will return the number of the day (1-366) that a datetime value represents within the year?" + ], + "items": [ + { + "id": "manual-strftime-vs-strptime", + "summary": "When do you use `strftime` versus `strptime`?", + "detail": "`strftime` formats a datetime into text; `strptime` parses text into a datetime object.", + "extra": "", + "code": "dt.strftime('%Y-%m-%d')\ndatetime.strptime('2024-05-20', '%Y-%m-%d')", + "table": null + }, + { + "id": "manual-timedelta-attrs", + "summary": "Which attributes exist directly on a `timedelta` object?", + "detail": "A `timedelta` stores `days`, `seconds`, and `microseconds`; hours or weeks must be derived or supplied when constructing it.", + "extra": "", + "code": "delta = end - start\nprint(delta.days, delta.seconds)", + "table": null + }, + { + "id": "manual-day-of-year", + "summary": "How can you compute the day number within the year from a datetime?", + "detail": "Subtract January 1st of the same year, take `.days`, and add 1 so January 1st becomes day 1.", + "extra": "", + "code": "def day_of_year(dt):\n return (dt - datetime(dt.year, 1, 1)).days + 1", + "table": null + } + ], + "generator": "lecture-first-build", + "model": null + }, + "ai_examples": [ + { + "id": "manual-datetime-format", + "kind": "correct", + "title": "Format a datetime with `strftime`", + "code": "from datetime import datetime\n\ndt = datetime(2024, 5, 20, 14, 30)\nprint(dt.strftime('%Y-%m-%d %H:%M'))", + "output": "2024-05-20 14:30", + "why": "Use `strftime` when the exam asks for a formatted string such as year-month-day or hour-minute.", + "status": "curated", + "subtopic_id": "w6-datetime-core", + "subtopic_title": "now, Timestamps, strftime, strptime, timedelta, and Date Arithmetic" + }, + { + "id": "manual-datetime-parse", + "kind": "correct", + "title": "Parse text with `strptime`", + "code": "from datetime import datetime\n\ndt = datetime.strptime('2024-05-20', '%Y-%m-%d')\nprint(dt)", + "output": "2024-05-20 00:00:00", + "why": "The format string must match the input text exactly, including separators.", + "status": "curated", + "subtopic_id": "w6-datetime-core", + "subtopic_title": "now, Timestamps, strftime, strptime, timedelta, and Date Arithmetic" + }, + { + "id": "manual-datetime-delta", + "kind": "correct", + "title": "Subtract datetimes to get a `timedelta`", + "code": "from datetime import datetime\n\nstart = datetime(2024, 1, 1)\nend = datetime(2024, 1, 4)\nprint((end - start).days)", + "output": "3", + "why": "Datetime subtraction gives a `timedelta`, whose `.days` attribute is often what exam questions want.", + "status": "curated", + "subtopic_id": "w6-datetime-core", + "subtopic_title": "now, Timestamps, strftime, strptime, timedelta, and Date Arithmetic" + }, + { + "id": "manual-datetime-replace", + "kind": "correct", + "title": "`.replace(...)` returns a new datetime", + "code": "from datetime import datetime\n\nd = datetime(2024, 5, 20)\nprint(d.replace(year=2026))\nprint(d)", + "output": "2026-05-20 00:00:00\n2024-05-20 00:00:00", + "why": "Datetime objects are immutable, so `.replace(...)` does not modify the original object in place.", + "status": "curated", + "subtopic_id": "w6-datetime-core", + "subtopic_title": "now, Timestamps, strftime, strptime, timedelta, and Date Arithmetic" }, { - "id": "ai-example-5", + "id": "manual-datetime-iso", "kind": "correct", - "title": "mygenerator = (x for x in range(100000000) if x%3 == 0 or x%4 == 0)", - "code": "mygenerator = (x for x in range(100000000) if x%3 == 0 or x%4 == 0)\nprint(next(mygenerator))\nprint(next(mygenerator))\nprint(next(mygenerator))\nprint(next(mygenerator))", - "why": "Expand `range(start, stop, step)` manually; `stop` is excluded and the next value is found by adding `step` each time.", + "title": "ISO and week-based helpers", + "code": "from datetime import datetime\n\nd = datetime(2024, 5, 20)\nprint(d.isoformat())\nprint(d.isoweekday())\nprint(d.isocalendar()[1])", "output": "", + "why": "Use ISO helpers when the exam asks for an ISO string, the weekday with Monday as 1, or the ISO week number.", "status": "curated", - "subtopic_id": "w6-generators-and-iterators-core", - "subtopic_title": "Iterator Protocol, Generator Functions, and Generator Comprehensions" + "subtopic_id": "w6-datetime-core", + "subtopic_title": "now, Timestamps, strftime, strptime, timedelta, and Date Arithmetic" }, { - "id": "ai-example-6", + "id": "manual-datetime-day-of-year", "kind": "correct", - "title": "class Mylist(list):", - "code": "class Mylist(list):\n def __iter__ (self):\n pass\nmyiterator = iter(Mylist([1,3,5]))\n\nprint(next(myiterator))\nprint(next(myiterator))\nprint(next(myiterator))\nprint(next(myiterator))", - "why": "", + "title": "Compute the day number within the year", + "code": "from datetime import datetime\n\ndef day_of_year(dt):\n return (dt - datetime(dt.year, 1, 1)).days + 1\n\nprint(day_of_year(datetime(2024, 5, 20)))", "output": "", + "why": "Subtract January 1st of the same year, then add 1 so January 1st becomes day 1.", "status": "curated", - "subtopic_id": "w6-generators-and-iterators-core", - "subtopic_title": "Iterator Protocol, Generator Functions, and Generator Comprehensions" + "subtopic_id": "w6-datetime-core", + "subtopic_title": "now, Timestamps, strftime, strptime, timedelta, and Date Arithmetic" }, { - "id": "ai-example-7", + "id": "manual-datetime-overlap", "kind": "correct", - "title": "def generatorfunction(start, stop, step):", - "code": "def generatorfunction(start, stop, step):\n while (num:=start) <= stop:\n yield num\n start += step\n return 'End of numbers'\nfor x in generatorfunction(1, 5, 2):\n print(x)", - "why": "For numeric variables, `a += 1` updates the stored value the same way as `a = a + 1`.", - "output": "", + "title": "Check whether two datetime intervals overlap", + "code": "from datetime import datetime\n\nstart_a = datetime(2024, 5, 20, 9, 0)\nend_a = datetime(2024, 5, 20, 11, 0)\nstart_b = datetime(2024, 5, 20, 10, 30)\nend_b = datetime(2024, 5, 20, 12, 0)\n\noverlaps = max(start_a, start_b) < min(end_a, end_b)\nprint(overlaps)", + "output": "True", + "why": "A reliable overlap check compares the later start with the earlier end; there is overlap only when the later start is still before the earlier end.", "status": "curated", - "subtopic_id": "w6-generators-and-iterators-core", - "subtopic_title": "Iterator Protocol, Generator Functions, and Generator Comprehensions" + "subtopic_id": "w6-datetime-core", + "subtopic_title": "now, Timestamps, strftime, strptime, timedelta, and Date Arithmetic" }, { - "id": "ai-example-8", + "id": "manual-datetime-strftime-loop", "kind": "correct", - "title": "def generatorfunction(start, stop, step):", - "code": "def generatorfunction(start, stop, step):\n while True:\n num = start\n start += step\n if num <= stop:\n yield num\n else:\n return 'End of numbers'\nprint(list(generatorfunction(1, 5, 2)))", - "why": "For numeric variables, `a += 1` updates the stored value the same way as `a = a + 1`.", - "output": "", + "title": "Do datetime math before `strftime` turns values into strings", + "code": "from datetime import datetime, timedelta\n\nday = datetime(2024, 1, 1)\nlabels = []\nfor _ in range(3):\n labels.append(day.strftime(\"%Y-%m-%d\"))\n day += timedelta(days=1)\nprint(labels)", + "output": "['2024-01-01', '2024-01-02', '2024-01-03']", + "why": "After `strftime`, the value is plain text, so increment the datetime object first and only store formatted strings as the final display step.", "status": "curated", - "subtopic_id": "w6-generators-and-iterators-core", - "subtopic_title": "Iterator Protocol, Generator Functions, and Generator Comprehensions" + "subtopic_id": "w6-datetime-core", + "subtopic_title": "now, Timestamps, strftime, strptime, timedelta, and Date Arithmetic" } ], - "recommended_ids": [ - "ks-900b394f8e", - "ks-cd030b9520", - "cs-0f95aa8463", - "cs-32bf0b7fdb", - "cs-078b563299", - "cs-a3d823b3c5" - ] - } - }, - { - "id": "w6-datetime", - "topic": "Datetime", - "canonical_topic": "w6-datetime", - "weeks": [ - 6 - ], - "week_id": "week-6", - "topic_meta": { - "week": 6, - "week_id": "week-6", - "week_title": "Week 6", - "topic_id": "w6-datetime", - "topic_title": "Datetime", - "topic_order": 3 - }, - "subtopics": [ - { - "id": "w6-datetime-core", - "title": "now, Timestamps, strftime, strptime, timedelta, and Date Arithmetic", - "order": 1, - "summary": "Use `datetime.now()` for current time, `strftime` to format, `strptime` to parse, and `timedelta` for date arithmetic.", - "summary": "Use `datetime.now()` for current time, `strftime`/`strptime` for formatting and parsing, ISO/week helpers for calendar fields, and `timedelta` for date arithmetic.", - "item_ids": { - "lecture_snippet_ids": [ - "ks-e643ee5e77", - "ks-755c23c4be", - "ks-169cc25be1", - "ks-86cd7ede1c", - "ks-662456da41" - ], - "exam_question_ids": [ - "exam-intro_python_sample_final_24_25-9-w6-datetime", - "exam-intro_python_sample_final_24_25-10-w6-datetime" - ], - "notebook_snippet_ids": [ - "cs-905c77e1f3", - "cs-bb6ae5efd3", - "cs-54af3f2f0d", - "cs-d9d6f95b5a", - "cs-6c8e441a09", - "cs-d495b08394", - "cs-b31e0142c3", - "cs-1887901826" - ], - "example_ids": [ - "manual-datetime-format", - "manual-datetime-parse", - "manual-datetime-delta", - "manual-datetime-replace", - "manual-datetime-iso", - "manual-datetime-day-of-year" - ], - "key_point_ids": [ - "kp-manual-datetime-now", - "kp-manual-datetime-format", - "kp-manual-datetime-delta", - "kp-manual-datetime-replace", - "kp-manual-datetime-iso", - "kp-manual-datetime-day-of-year" - ] - } - } - ], - "exam_stats": { - "total_hits": 2, - "by_exam": { - "intro_python_sample_final_24_25": 2 + "ai_summary": { + "status": "curated", + "content": "Use `datetime.now()` for current time, `strftime`/`strptime` for formatting and parsing, ISO/week helpers for calendar fields, and `timedelta` for date arithmetic.", + "generator": "lecture-first-build", + "model": null }, - "coverage_count": 1 - }, - "related_topics": [ - "now, Timestamps, strftime, strptime, timedelta, and Date Arithmetic" - ], - "trap_patterns": [], - "sections": { + "exam_questions": [ + { + "id": "exam-intro_python_sample_final_24_25-9-w6-datetime", + "exam_label": "intro_python_sample_final_24_25", + "exam_source": "materials/post_midterm/Sample Final plus answers.pdf", + "year": "2024", + "number": 9, + "week": 6, + "topic": "Datetime (Parsing)", + "subtopic_id": "w6-datetime-core", + "subtopic_title": "now, Timestamps, strftime, strptime, timedelta, and Date Arithmetic", + "question": "Suppose that you call the function like this: get_months([\"03/02/2013\", \"03.02.2013\", \"03-02-2013\"]). What does the function call return?", + "code_context": "from datetime import datetime\ndef get_months(date_strings):\n dates = []\n for date_str in date_strings:\n if \"-\" in date_str:\n dates.append(datetime.strptime(date_str, \"%d-%m-%Y\"))\n elif \"/\" in date_str:\n dates.append(datetime.strptime(date_str, \"%m/%d/%Y\"))\n else:\n dates.append(None)\n return [date.month if date is not None else None for date in dates]", + "options": { + "A": "[3, None, 2]", + "B": "[2, None, 3]", + "C": "[3, 2]", + "D": "[2, 3]" + }, + "correct": "A", + "explanation": "1st string: contains '/' so it uses %m/%d/%Y -> month 3. 2nd: contains neither '-' nor '/' -> None. 3rd: contains '-' so it uses %d-%m-%Y -> month 2." + }, + { + "id": "exam-intro_python_sample_final_24_25-10-w6-datetime", + "exam_label": "intro_python_sample_final_24_25", + "exam_source": "materials/post_midterm/Sample Final plus answers.pdf", + "year": "2024", + "number": 10, + "week": 6, + "topic": "Datetime (Arithmetic)", + "subtopic_id": "w6-datetime-core", + "subtopic_title": "now, Timestamps, strftime, strptime, timedelta, and Date Arithmetic", + "question": "Which of the following code segments will return the number of the day (1-366) that a datetime value represents within the year?", + "code_context": "", + "options": { + "A": "def day_of_year(dt):\n return (dt - datetime(dt.year, 1, 1)).days + 1", + "B": "def day_of_year(dt):\n return timedelta(dt - datetime(dt.year, 1, 1)) + 1", + "C": "def day_of_year(dt):\n return dt - datetime(dt.year, 1, 1) + 1", + "D": "def day_of_year(dt):\n return (dt - datetime(dt.year, 1, 0)).days" + }, + "correct": "A", + "explanation": "Subtracting two datetime objects results in a timedelta object. Accessing the .days attribute gives the difference as an integer. Adding 1 makes it 1-based (Jan 1st = day 1)." + } + ], + "key_points_to_remember": [ + { + "id": "kp-manual-datetime-now", + "text": "`datetime.now()` gives the current local datetime; use `.timestamp()` only when you specifically need seconds since the Unix epoch." + }, + { + "id": "kp-manual-datetime-format", + "text": "`strftime` formats a datetime into text; `strptime` parses text into a datetime object." + }, + { + "id": "kp-manual-datetime-delta", + "text": "Subtracting two datetimes gives a `timedelta`; its most-used direct attributes are `.days`, `.seconds`, and `.microseconds`." + }, + { + "id": "kp-manual-datetime-replace", + "text": "Datetime objects are immutable, so `.replace(...)` returns a new datetime instead of modifying the original one." + }, + { + "id": "kp-manual-datetime-iso", + "text": "Use `isoformat()` for an ISO-style timestamp, `isoweekday()` for Monday=1..Sunday=7, and `isocalendar()` when you need ISO year/week information." + }, + { + "id": "kp-manual-datetime-day-of-year", + "text": "The day number within the year can be formatted with `%j` or computed with `(dt - datetime(dt.year, 1, 1)).days + 1`." + } + ], "lecture_snippets": [ { "id": "ks-e643ee5e77", @@ -14996,77 +15794,33 @@ "source": "materials/post_midterm/Lecture Week 6.pptx", "source_type": "lecture", "topic": "Datetime", - "subtopic_id": "w6-datetime-core", - "subtopic_title": "now, Timestamps, strftime, strptime, timedelta, and Date Arithmetic", - "title": "Timedelta and Date Arithmetic", - "explanation": "Timedelta objects represent durations. Subtracting two datetimes creates a timedelta; adding a timedelta to a datetime shifts the date.", - "code_examples": [ - { - "description": "Calculating days difference", - "code": "from datetime import datetime, timedelta\ndiff = datetime(2024, 1, 1) - datetime(2023, 1, 1)\nprint(diff.days)" - } - ] - }, - { - "id": "ks-662456da41", - "week": 6, - "source": "materials/post_midterm/Lecture Week 6.pptx", - "source_type": "lecture", - "topic": "Datetime", - "subtopic_id": "w6-datetime-core", - "subtopic_title": "now, Timestamps, strftime, strptime, timedelta, and Date Arithmetic", - "title": "The replace() Method", - "explanation": "Datetime objects are immutable. The replace() method creates a new datetime object with specific attributes changed.", - "code_examples": [ - { - "description": "Changing the year of a date", - "code": "from datetime import datetime\nd = datetime.now().replace(year=2026)" - } - ] - } - ], - "exam_questions": [ - { - "id": "exam-intro_python_sample_final_24_25-9-w6-datetime", - "exam_label": "intro_python_sample_final_24_25", - "exam_source": "materials/post_midterm/Sample Final plus answers.pdf", - "year": "2024", - "number": 9, - "week": 6, - "topic": "Datetime (Parsing)", - "subtopic_id": "w6-datetime-core", - "subtopic_title": "now, Timestamps, strftime, strptime, timedelta, and Date Arithmetic", - "question": "Suppose that you call the function like this: get_months([\"03/02/2013\", \"03.02.2013\", \"03-02-2013\"]). What does the function call return?", - "code_context": "from datetime import datetime\ndef get_months(date_strings):\n dates = []\n for date_str in date_strings:\n if \"-\" in date_str:\n dates.append(datetime.strptime(date_str, \"%d-%m-%Y\"))\n elif \"/\" in date_str:\n dates.append(datetime.strptime(date_str, \"%m/%d/%Y\"))\n else:\n dates.append(None)\n return [date.month if date is not None else None for date in dates]", - "options": { - "A": "[3, None, 2]", - "B": "[2, None, 3]", - "C": "[3, 2]", - "D": "[2, 3]" - }, - "correct": "A", - "explanation": "1st string: contains '/' so it uses %m/%d/%Y -> month 3. 2nd: contains neither '-' nor '/' -> None. 3rd: contains '-' so it uses %d-%m-%Y -> month 2." + "subtopic_id": "w6-datetime-core", + "subtopic_title": "now, Timestamps, strftime, strptime, timedelta, and Date Arithmetic", + "title": "Timedelta and Date Arithmetic", + "explanation": "Timedelta objects represent durations. Subtracting two datetimes creates a timedelta; adding a timedelta to a datetime shifts the date.", + "code_examples": [ + { + "description": "Calculating days difference", + "code": "from datetime import datetime, timedelta\ndiff = datetime(2024, 1, 1) - datetime(2023, 1, 1)\nprint(diff.days)" + } + ] }, { - "id": "exam-intro_python_sample_final_24_25-10-w6-datetime", - "exam_label": "intro_python_sample_final_24_25", - "exam_source": "materials/post_midterm/Sample Final plus answers.pdf", - "year": "2024", - "number": 10, + "id": "ks-662456da41", "week": 6, - "topic": "Datetime (Arithmetic)", + "source": "materials/post_midterm/Lecture Week 6.pptx", + "source_type": "lecture", + "topic": "Datetime", "subtopic_id": "w6-datetime-core", "subtopic_title": "now, Timestamps, strftime, strptime, timedelta, and Date Arithmetic", - "question": "Which of the following code segments will return the number of the day (1-366) that a datetime value represents within the year?", - "code_context": "", - "options": { - "A": "def day_of_year(dt):\n return (dt - datetime(dt.year, 1, 1)).days + 1", - "B": "def day_of_year(dt):\n return timedelta(dt - datetime(dt.year, 1, 1)) + 1", - "C": "def day_of_year(dt):\n return dt - datetime(dt.year, 1, 1) + 1", - "D": "def day_of_year(dt):\n return (dt - datetime(dt.year, 1, 0)).days" - }, - "correct": "A", - "explanation": "Subtracting two datetime objects results in a timedelta object. Accessing the .days attribute gives the difference as an integer. Adding 1 makes it 1-based (Jan 1st = day 1)." + "title": "The replace() Method", + "explanation": "Datetime objects are immutable. The replace() method creates a new datetime object with specific attributes changed.", + "code_examples": [ + { + "description": "Changing the year of a date", + "code": "from datetime import datetime\nd = datetime.now().replace(year=2026)" + } + ] } ], "notebook_snippets": [ @@ -15177,141 +15931,6 @@ "outputs": [] } ], - "ai_summary": { - "status": "curated", - "content": "Use `datetime.now()` for current time, `strftime`/`strptime` for formatting and parsing, ISO/week helpers for calendar fields, and `timedelta` for date arithmetic.", - "generator": "lecture-first-build", - "model": null - }, - "ai_common_questions": { - "status": "curated", - "bullets": [ - "Suppose that you call the function like this: get_months([\"03/02/2013\", \"03.02.2013\", \"03-02-2013\"]). What does the function call return?", - "Which of the following code segments will return the number of the day (1-366) that a datetime value represents within the year?" - ], - "items": [ - { - "id": "manual-strftime-vs-strptime", - "summary": "When do you use `strftime` versus `strptime`?", - "detail": "`strftime` formats a datetime into text; `strptime` parses text into a datetime object.", - "extra": "", - "code": "dt.strftime('%Y-%m-%d')\ndatetime.strptime('2024-05-20', '%Y-%m-%d')", - "table": null - }, - { - "id": "manual-timedelta-attrs", - "summary": "Which attributes exist directly on a `timedelta` object?", - "detail": "A `timedelta` stores `days`, `seconds`, and `microseconds`; hours or weeks must be derived or supplied when constructing it.", - "extra": "", - "code": "delta = end - start\nprint(delta.days, delta.seconds)", - "table": null - }, - { - "id": "manual-day-of-year", - "summary": "How can you compute the day number within the year from a datetime?", - "detail": "Subtract January 1st of the same year, take `.days`, and add 1 so January 1st becomes day 1.", - "extra": "", - "code": "def day_of_year(dt):\n return (dt - datetime(dt.year, 1, 1)).days + 1", - "table": null - } - ], - "generator": "lecture-first-build", - "model": null - }, - "key_points_to_remember": [ - { - "id": "kp-manual-datetime-now", - "text": "`datetime.now()` gives the current local datetime; use `.timestamp()` only when you specifically need seconds since the Unix epoch." - }, - { - "id": "kp-manual-datetime-format", - "text": "`strftime` formats a datetime into text; `strptime` parses text into a datetime object." - }, - { - "id": "kp-manual-datetime-delta", - "text": "Subtracting two datetimes gives a `timedelta`; its most-used direct attributes are `.days`, `.seconds`, and `.microseconds`." - }, - { - "id": "kp-manual-datetime-replace", - "text": "Datetime objects are immutable, so `.replace(...)` returns a new datetime instead of modifying the original one." - }, - { - "id": "kp-manual-datetime-iso", - "text": "Use `isoformat()` for an ISO-style timestamp, `isoweekday()` for Monday=1..Sunday=7, and `isocalendar()` when you need ISO year/week information." - }, - { - "id": "kp-manual-datetime-day-of-year", - "text": "The day number within the year can be formatted with `%j` or computed with `(dt - datetime(dt.year, 1, 1)).days + 1`." - } - ], - "ai_examples": [ - { - "id": "manual-datetime-format", - "kind": "correct", - "title": "Format a datetime with `strftime`", - "code": "from datetime import datetime\n\ndt = datetime(2024, 5, 20, 14, 30)\nprint(dt.strftime('%Y-%m-%d %H:%M'))", - "output": "2024-05-20 14:30", - "why": "Use `strftime` when the exam asks for a formatted string such as year-month-day or hour-minute.", - "status": "curated", - "subtopic_id": "w6-datetime-core", - "subtopic_title": "now, Timestamps, strftime, strptime, timedelta, and Date Arithmetic" - }, - { - "id": "manual-datetime-parse", - "kind": "correct", - "title": "Parse text with `strptime`", - "code": "from datetime import datetime\n\ndt = datetime.strptime('2024-05-20', '%Y-%m-%d')\nprint(dt)", - "output": "2024-05-20 00:00:00", - "why": "The format string must match the input text exactly, including separators.", - "status": "curated", - "subtopic_id": "w6-datetime-core", - "subtopic_title": "now, Timestamps, strftime, strptime, timedelta, and Date Arithmetic" - }, - { - "id": "manual-datetime-delta", - "kind": "correct", - "title": "Subtract datetimes to get a `timedelta`", - "code": "from datetime import datetime\n\nstart = datetime(2024, 1, 1)\nend = datetime(2024, 1, 4)\nprint((end - start).days)", - "output": "3", - "why": "Datetime subtraction gives a `timedelta`, whose `.days` attribute is often what exam questions want.", - "status": "curated", - "subtopic_id": "w6-datetime-core", - "subtopic_title": "now, Timestamps, strftime, strptime, timedelta, and Date Arithmetic" - }, - { - "id": "manual-datetime-replace", - "kind": "correct", - "title": "`.replace(...)` returns a new datetime", - "code": "from datetime import datetime\n\nd = datetime(2024, 5, 20)\nprint(d.replace(year=2026))\nprint(d)", - "output": "2026-05-20 00:00:00\n2024-05-20 00:00:00", - "why": "Datetime objects are immutable, so `.replace(...)` does not modify the original object in place.", - "status": "curated", - "subtopic_id": "w6-datetime-core", - "subtopic_title": "now, Timestamps, strftime, strptime, timedelta, and Date Arithmetic" - }, - { - "id": "manual-datetime-iso", - "kind": "correct", - "title": "ISO and week-based helpers", - "code": "from datetime import datetime\n\nd = datetime(2024, 5, 20)\nprint(d.isoformat())\nprint(d.isoweekday())\nprint(d.isocalendar()[1])", - "output": "", - "why": "Use ISO helpers when the exam asks for an ISO string, the weekday with Monday as 1, or the ISO week number.", - "status": "curated", - "subtopic_id": "w6-datetime-core", - "subtopic_title": "now, Timestamps, strftime, strptime, timedelta, and Date Arithmetic" - }, - { - "id": "manual-datetime-day-of-year", - "kind": "correct", - "title": "Compute the day number within the year", - "code": "from datetime import datetime\n\ndef day_of_year(dt):\n return (dt - datetime(dt.year, 1, 1)).days + 1\n\nprint(day_of_year(datetime(2024, 5, 20)))", - "output": "", - "why": "Subtract January 1st of the same year, then add 1 so January 1st becomes day 1.", - "status": "curated", - "subtopic_id": "w6-datetime-core", - "subtopic_title": "now, Timestamps, strftime, strptime, timedelta, and Date Arithmetic" - } - ], "recommended_ids": [ "exam-intro_python_sample_final_24_25-9-w6-datetime", "exam-intro_python_sample_final_24_25-10-w6-datetime", @@ -15321,8 +15940,73 @@ "ks-86cd7ede1c", "cs-905c77e1f3", "cs-bb6ae5efd3" - ] - } + ], + "homework_snippets": [], + "homework_recommended_ids": [] + }, + "subtopics": [ + { + "id": "w6-datetime-core", + "item_ids": { + "exam_question_ids": [ + "exam-intro_python_sample_final_24_25-9-w6-datetime", + "exam-intro_python_sample_final_24_25-10-w6-datetime" + ], + "example_ids": [ + "manual-datetime-overlap", + "manual-datetime-strftime-loop", + "manual-datetime-format", + "manual-datetime-parse", + "manual-datetime-delta", + "manual-datetime-replace", + "manual-datetime-iso", + "manual-datetime-day-of-year" + ], + "key_point_ids": [ + "kp-manual-datetime-now", + "kp-manual-datetime-format", + "kp-manual-datetime-delta", + "kp-manual-datetime-replace", + "kp-manual-datetime-iso", + "kp-manual-datetime-day-of-year" + ], + "lecture_snippet_ids": [ + "ks-e643ee5e77", + "ks-755c23c4be", + "ks-169cc25be1", + "ks-86cd7ede1c", + "ks-662456da41" + ], + "notebook_snippet_ids": [ + "cs-905c77e1f3", + "cs-bb6ae5efd3", + "cs-54af3f2f0d", + "cs-d9d6f95b5a", + "cs-6c8e441a09", + "cs-d495b08394", + "cs-b31e0142c3", + "cs-1887901826" + ] + }, + "order": 1, + "summary": "Use `datetime.now()` for current time, `strftime`/`strptime` for formatting and parsing, ISO/week helpers for calendar fields, and `timedelta` for date arithmetic.", + "title": "now, Timestamps, strftime, strptime, timedelta, and Date Arithmetic" + } + ], + "topic": "Datetime", + "topic_meta": { + "week": 6, + "week_id": "week-6", + "week_title": "Week 6", + "topic_id": "w6-datetime", + "topic_title": "Datetime", + "topic_order": 3 + }, + "trap_patterns": [], + "week_id": "week-6", + "weeks": [ + 6 + ] } ], "deck_groups": [ @@ -15632,5 +16316,24 @@ } ] } - ] + ], + "meta": { + "generated_from": "data/study_db.json", + "generator": "build_topic_cards.py", + "course": "Introduction to Python", + "weeks_covered": [ + 1, + 2, + 3, + 4, + 5, + 6 + ], + "total_cards": 27, + "notes": [ + "Cards are materialized directly from the lecture-first canonical study database.", + "Each card maps to one sidebar topic, with subtopics rendered inside the topic detail page.", + "AI-style summary, examples, and key points are deterministic curated fallbacks until optional enrichment scripts overwrite them." + ] + } }