{ "cells": [ { "cell_type": "markdown", "metadata": {}, "source": [ "# Python 101 \n", "## Part III.\n", "\n", "---" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Install dependencies with:\n", "\n", "```bash\n", "pip install moviepy\n", "```" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "import webbrowser\n", "from helpers import *" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "---\n", "\n", "## Control structures\n", "\n", "### For Loops\n", "\n", "A **for loop** lets you repeat actions for a sequence of values. \n", "For example, you can loop over a **sequence of numbers** using `range(start, end, step)`:\n", "\n", "- `start`: where the sequence begins (inclusive) \n", "- `end`: where the sequence ends (exclusive) \n", "- `step`: the amount to increase each time" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "start = 1\n", "end = 11\n", "step = 1\n", "for number in range(start, end, step):\n", " print(number)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "You can also loop through **any collection** (like a list) or even directly over the characters of a string." ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "my_list_of_things = [\n", " 'a', 'b', 'c', 'd',\n", " 1, 2, 3, 4,\n", " 'foo', 'bar', 'baz', 'qux'\n", "]\n", "\n", "for thing in my_list_of_things:\n", " print(thing)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Notice in the example below that we customize `print(..., end='')` to avoid automatic line breaks:" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "for char in 'the holy grail':\n", " if char == ' ':\n", " print('space', end='')\n", " else:\n", " print(char, end='')" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "### While loop\n", "\n", "A **while loop** keeps running *as long as* a condition is `True`. \n", "This is useful when you don’t know in advance how many times you’ll need to loop.\n", "\n", "**Be careful**: if the condition never becomes `False`, the loop will run forever." ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "condition = True\n", "counter = 1\n", "while(condition):\n", " print(counter)\n", " counter += 1\n", " if counter > 10:\n", " condition = False" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "i = 0\n", "string = 'the holy grail'\n", "while not string[i] == ' ':\n", " print(string[i])\n", " i += 1" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "### Exercise: Ask for a proper e-mail address\n", "\n", "Users can be malicious or lousy and often provide wrong email address." ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [] }, { "cell_type": "markdown", "metadata": {}, "source": [ "### Exercise: Prisoner's dilemma\n", "\n", "Two members of a criminal-gang are arrested and imprisoned. Each prisoner is in solitary confinement with no means of communicating with the other. The prosecutors lack sufficient evidence to convinct the pair on the principal charge. They hope to get both sentenced to a year in prison on a lesser charge. Simultaneously, the prosecutors offer each prisoner a bargain. Each prisoner is given the oppurtunity either to: betray the other by testifying that the other committed the crime, or to cooperate with the other by remaining silent. The offer is: \n", "\n", "- If A and B each betray the other, each of them serves 6 years in prison\n", "- If A betrays B but B remains silent, A will be set free and B will serve 10 years in prison (and vice versa)\n", "- If A and B both remain silent, both of them will only serve 6 months in prison (on the lesser charge)\n", "\n", "\n", "We represent the game as a **list of dictionaries**, where each dictionary contains:\n", "- the choice of **player1** (the user) \n", "- the choice of **player2** (the AI) \n", "- the resulting **outcome** \n", "\n", "**Your task:** \n", "Write a for-loop that:\n", "1. Iterates over the list of decisions. \n", "2. Checks whether both the user’s and AI’s choices match the current dictionary entry. \n", "3. If so, prints the correct outcome." ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "decisions = [\n", " {\"player1\": \"betray\", \"player2\": \"betray\", \"outcome\": \"Both serve 6 years\"},\n", " {\"player1\": \"betray\", \"player2\": \"silent\", \"outcome\": \"Player1 free, Player2 serves 10 years\"},\n", " {\"player1\": \"silent\", \"player2\": \"betray\", \"outcome\": \"Player1 serves 10 years, Player2 free\"},\n", " {\"player1\": \"silent\", \"player2\": \"silent\", \"outcome\": \"Both serve 6 months\"},\n", "]\n", "\n", "user_choice = \"betray\"\n", "ai_choice = random.choice([\"betray\", \"silent\"])" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "#### Step 1 – Write a condition for one case \n", "\n", "Take the first decision (`decisions[0]`) and check if it matches the `user_choice` and `ai_choice`. \n", "If it matches, print the outcome. \n", "\n", "**Task:** Write the condition inside the `if` statement." ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "decision = decisions[0]" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "#### Step 2 – Generalize with a loop \n", "\n", "Instead of checking only the first dictionary, we want to check **all possible decisions**. \n", "\n", "**Task:** Replace the hard-coded index with a `for` loop that iterates through the `decisions` list." ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [] }, { "cell_type": "markdown", "metadata": {}, "source": [ "---\n", "\n", "## List Comprehensions \n", "\n", "A **list comprehension** is a shorthand way to create a new list in Python. \n", "It’s especially useful when you want to **transform** or **filter** elements from another list. \n", "\n", "General pattern:\n", "```python\n", "[ expression for item in iterable if condition ]\n", "```\n", "\n", "- **expression** → what you want in the new list\n", "- **for item in iterable** → loop over a sequence\n", "- **if condition** (optional) → filter items\n", "\n", "This is equivalent to writing a for loop, but in a single compact line." ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "### Transforming a for-loop into a list comprehension \n", "\n", "Let’s say we want the squares of numbers 1–5. \n", "\n", "**For loop version:**" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "manual_squares = []\n", "for n in range(1, 6):\n", " manual_squares.append(n**2)\n", "\n", "print(manual_squares)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "List comprehension version:" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "squares = [n**2 for n in range(1, 6)]\n", "print(squares)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Steps to transform:\n", "1. Identify the for loop that builds a list.\n", "1. Move the statement from inside the loop (`.append(...)`) to the front.\n", "1. Remove the colon.\n", "1. Add square brackets around the whole thing." ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Other examples:" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "sequence = [1, 2, 3, 4]\n", "print([item for item in sequence])\n", "print([item * 2 for item in sequence])" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Use the `.join()` function to merge strings with a separator string:" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "sequence = ['a', 'b', 'c']\n", "separator = ''\n", "print(separator.join([item for item in sequence]))\n", "separator = ', '\n", "print(separator.join([item for item in sequence]))" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "### Quick Exercise \n", "\n", "**Tasks:** \n", "Using list comprehensions, do the following: \n", "\n", "1. From `numbers = list(range(10))`, create a list of even numbers. \n", "2. From `words = [\"apple\", \"banana\", \"cherry\", \"date\"]`, create a list of word lengths. \n", "3. From `sentence = \"the quick brown fox\"`, create a list of all uppercase letters (skip the spaces). " ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "numbers = list(range(10))\n", "words = [\"apple\", \"banana\", \"cherry\", \"date\"]\n", "sentence = \"the quick brown fox\"\n", "\n", "# Write your list comprehensions here\n", "evens = numbers\n", "word_lengths = words\n", "uppercase_letters = sentence" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "---\n", "\n", "## Exercises\n", "\n", "__1. Given a list of urls, print the hungarian sites!__" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "urls = ['bbc.com', '444.hu', 'nbc.com', 'newyorktimes.com', 'origo.hu', 'index.hu', 'got.hummus.org']\n" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "### Exercise: The Seven Bridges of Königsberg \n", "\n", "The city of Königsberg (now Kaliningrad) had **seven bridges** connecting different parts of the city. \n", "Euler proved that it is **impossible** to cross all seven bridges exactly once — this was the birth of **graph theory**! \n", "\n", "\n", "\n", "\n", "\n", "
\n", "source: Wikipedia\n", "
\n", "\n", "We’ll work with two pieces of data: \n", "1. A dictionary of bridges (`bridges`), where each key is a bridge ID and each value is its length. \n", "2. A list of routes (`routes`), where each route is a list of bridge IDs. \n", "\n", "Our goal is to compute the total length of each possible route. \n", "\n", "

Let the name of the bridges the following:

\n", " \n", "" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "distances = {\n", " 'ABup': 3,\n", " 'ABdown': 4,\n", " 'ADup': 3,\n", " 'ADdown': 2,\n", " 'AC': 10,\n", " 'BC': 7,\n", " 'CD': 6,\n", "}\n", "routes = [\n", " ['BC', 'ABdown', 'AC', 'CD', 'ADup', 'ADdown', 'ADdown', 'ABup'],\n", " ['ABup', 'ABdown', 'ADdown', 'ADup', 'AC', 'CD', 'ADup', 'ABup', 'BC'],\n", " ['ADdown', 'CD', 'BC', 'ABup', 'ABdown', 'BC', 'AC', 'ADup'],\n", "]" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "#### Step 1 – Extract a single bridge length \n", "\n", "Pick one bridge from the data to see how it’s structured. \n", "- Let’s take the first bridge ID from the first route in the `routes` list. \n", "- Store it in a variable called `bridge`. \n", "- Then use the dictionary to get its length. \n", "\n", "**Task:** Print the bridge ID and its length." ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "route = routes[0]\n", "bridge = route[0]\n" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "#### Step 2 – Iterate over one route \n", "\n", "Now let’s calculate the lengths for **all bridges in a single route**. \n", "- Take the first route (`routes[0]`) and store it in a variable called `route`. \n", "- Loop through the bridge IDs in `route`. \n", "- For each bridge, print its length. \n", "\n", "**Task:** Print the sequence of lengths for that route." ] }, { "cell_type": "markdown", "metadata": {}, "source": [] }, { "cell_type": "markdown", "metadata": {}, "source": [ "#### Step 3 – Compute the total length of one route \n", "\n", "Instead of printing each length, let’s **sum them up**. \n", "- Create a variable `route_length` and set it to 0. \n", "- Inside the loop, add each bridge length to `route_length`. \n", "- After the loop, print the total. \n", "\n", "**Task:** Use a counter variable to accumulate the total length." ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [] }, { "cell_type": "markdown", "metadata": {}, "source": [ "#### Step 4 – Compute the length for every route \n", "\n", "Finally, let’s put it all together. \n", "- Loop through **all routes** in `routes`. \n", "- For each route, calculate its total length (like in Step 3). \n", "- Print the route and its total length. \n", "\n", "**Task:** Use a nested loop: one loop for routes, one for bridges inside each route." ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [] }, { "cell_type": "markdown", "metadata": {}, "source": [ "---\n", "\n", "## Functions\n", "\n", "**How to define a function?**" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "def my_function(): # function header\n", " print(\"Hello World!\") # function body" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "**How to \"call\" a function?** " ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "my_function()" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "**Function arguments**\n", "\n", "The variables in the brackets are called arguments. You can use them as variables inside the function but you have to provide them when you call the function." ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "def my_updated_function(name):\n", " print(f\"Hello {name}!\")" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "name = '' # enter your name\n", "my_updated_function(name)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "**Docstrings and return values**\n", "\n", "- Docstrings are used to document the function's behaviour\n", "- Return values are the values that are returned to the caller - you can use the returned value(s) where you called the function" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "def my_updated_updated_function(greeting, name):\n", " \"\"\"This is my super descriptive docstring\n", " for my super advanced function.\n", " Arguments:\n", " greeting: the greeting word.\n", " name: the name of the greeted one.\"\"\"\n", " return f\"{greeting} {name}!\"" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "greeting = 'Aye-aye'\n", "my_greeting = my_updated_updated_function(greeting, name)\n", "print(my_greeting)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "**Getting some help** == getting the docstring of a function\n", "- Using the built-in `help()` function\n", "- In Jupyter Notebook pressing [shift]-[tab] twice inside a functions' brackets" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "help(my_updated_updated_function)" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "print('My docstring:')\n", "print(my_updated_updated_function.__doc__)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "You can provide parameters to functions by **position** or by **keyword**. \n", "\n", "Positional parameters are just parameter values in the right order, keyword parameters are specified with the name of the parameter followed by the value you want to set using the `parameter_name=value` pattern. \n", "\n", "Keyword parameters do not have to follow the right order, you can set them as you like. You can mix the two together by first setting the positional parameters followed by the keyword ones.\n", "\n", "Here are a few examples:" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "# using positional parameters only:\n", "my_updated_updated_function('Hi', 'name')\n", "\n", "# using keyword parameters only (in custom order):\n", "my_updated_updated_function(name=\"name\", greeting=\"Hi\")\n", "\n", "# mixing the two style:\n", "my_updated_updated_function(\"Hi\", name=\"name\")" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "# the one that causes error: keyword paramter followed by a positional one\n", "my_updated_updated_function(name=\"name\", \"Hi\")" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "---\n", "\n", "## Let's do some...\n", "\n", "\n", "
\n", "\n", "### Cool library of the week: moviepy\n", "- Edit videos in a few lines\n", "\n", "Real life example:\n", "- Our friend recorded a video with his/her cell in portrait mode. Awful! Let's rotate that video!" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "from moviepy import *\n", "\n", "clip = VideoFileClip('./Rick Astley - Never Gonna Give You Up (Official Music Video)-dQw4w9WgXcQ.mkv')\n", "clip = clip.with_effects([vfx.Rotate(90)])\n", "clip.write_videofile(\"./never_gonna_give_you_up_90.mp4\")" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "---\n", "\n", "## Let's have some fun! a.k.a \n", "## It's your turn - write the missing code snippets!\n", "\n", "Before we jump into action:\n", "\n", "---\n", "\n", "__** DISCLAIMER **__\n", "\n", "There are several functions defined in the `helpers.py` file. We loaded every function from it in the very first (ok, technically the second) cell so we can use those functions in the notebook. If in the following excersises you get a `hint` to use a function, it is usually defined there, and includes docstrings - don't forget to read what a function does before using it!\n", "\n", "__** END OF DISCLAIMER **__\n", "\n", "---\n", "\n", "#### 1. Now that we have everything we need, let's use it for a real life example: \n", "\n", "A `.csv` file called **`bookmark.csv`** contains links in two categories: \n", "\n", "- learn\n", "- fun\n", "\n", "Open every link from one of the categories in your browser by reading the file contents, iterating over the rows, and examining if the type of link matches with the selected category. Open the link using the `webbrowser.open_new_tab(url)` function.\n", "\n", "##### a) Import data from the `bookmark.csv` into `url_data` variable!\n", "**Hints:**\n", "- the date resides in the `data` folder\n", "- use the `import_from_csv` function\n", "- addition works with strings (make use of the `base` variable)" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "base = './data/'\n", "url_data = # write a function call here\n", "print(url_data)" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "reason = random.choice(['learn', 'fun'])\n", "reason" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "##### b) Write a function which will open every link of the given type (learn/fun)!\n", "\n", "*Name*: opentabs \n", "*Arguments*: reason, url_data \n", "\n", "**Hints:**\n", "- you can use the `webbrowser.open_new_tab()` function\n", "- basic steps:\n", " - define\n", " - iterate\n", " - check type\n", " - open link" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "def opentabs(reason, url_data):\n", " # write your code here" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "opentabs(reason, url_data)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "#### 2. We want to know if a file is in the current directory. Write a function which will tell you so.\n", "**Hint:** use the `list_files()` function to get the files from the working directory." ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "def isin(filename):\n", " # return the boolean result" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "print(isin('helpers.py'))\n", "print(isin('awesome.txt'))" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "#### 3. Our friend recommends us a new series. \n", "We downloaded the full series (7 seasons) and we believe that we downloaded all of the subtitles as well - although we're not that sure. Check if we miss some! We created a simulated `download_series` function for you, this will simply generate empty files for you to experiment with.\n", "\n", "##### a) \"Download\" the series with the function called `download_series`. \n", "\n", "\n", "\n", "**Hint:** use the `help` function!" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "# download_series function call goes here!\n" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "##### b) Write a function which outputs those video filenames which are missing subtitles. \n", "The video file's extension is `.avi`, the subtitle file's extension is `.srt`. \n", "We only accept a subtitle if it's name is perfectly matches the video's name. \n", "\n", "- Create a list of avis and a list of srts. \n", "- Iterate over the avis list\n", "- In the loop, check if the actual item is in the srts list" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "def missing_subtitle(directory):\n", " # list, iterate, check, print\n" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "missing_subtitle('super_series')" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "#### 4. Display every image from the current directory (use the `list_files()` function)! \n", "Valid image file extensions are `.png`, `.jpg`, `.jpeg`." ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "def images():\n", " # list, iterate, check, print\n" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "images()" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "#### 5. There is a csv file with picture urls. Display every picture from the CSV.\n", "\n", "\n", "The csv file is in the data folder and called `pics.csv`. \n", "- Iterate over the image_links\n", "- Use the `print_image` function with _type='net' parameter" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "image_links = import_from_csv(base + 'pictures.csv')" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "# iterate, check, print\n" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [] }, { "cell_type": "markdown", "metadata": {}, "source": [ "#### 6. We have a csv file with cursewords. Write a function which substitutes the words from the csv in an input text.\n", "\n", "The csv file is in the data folder and called `cursewords.csv`.\n", "1. Prepare cursewords: \n", " - Read the csv file contents using the function from the previous exercise\n", " - Create the list of cursewords from the function's output\n", "2. Filter cursewords from input text:\n", " - Split the read text into words\n", " - Iterate over the words\n", " - Check if the current word is a curseword\n", " - Change the word to the `substitution` parameter\n", "\n", "**Hints:**\n", " - `import_from_csv(path)` reads the csv data to a list\n", " - `string.split(splitchar)` splits the string\n", " - `string.lower()` will lower every char in the string\n", " - `string.strip(char_to_strip)`\n", " - `string.join(iterable)` will join the iterable elements together, the string will be the separator \n", " - commas will be part of the words" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "def clean(text, substitution='*#%=!'):\n", " # read, split, iterate, check, substitute\n" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "print(clean('A monkey and a donkey went to visit Boby .'))" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "#### 7. Statistics!\n", "\n", "Let's say you flip a coin 50 times and it was heads 37 times. Would you say that it is a fair coin with 95% certainty? \n", "At a regular statistics course you'd perform a t-test. But there is an easier way with python! \n", "Simulate the 50 coin flipping 10000 times and see how many times were there 37 or more heads in the 50 flips." ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "# write your code here" ] } ], "metadata": { "anaconda-cloud": {}, "kernelspec": { "display_name": "Python 3 (ipykernel)", "language": "python", "name": "python3" }, "language_info": { "codemirror_mode": { "name": "ipython", "version": 3 }, "file_extension": ".py", "mimetype": "text/x-python", "name": "python", "nbconvert_exporter": "python", "pygments_lexer": "ipython3", "version": "3.11.5" } }, "nbformat": 4, "nbformat_minor": 1 }