{ "cells": [ { "cell_type": "markdown", "id": "composite-saturday", "metadata": {}, "source": [ "# Lecture 2: Quick(ish) Introduction to Python" ] }, { "cell_type": "markdown", "id": "velvet-helping", "metadata": {}, "source": [ "The goal of this lecture is to give you some of the basics. It's not possible for us to cover **everything** you'll need to know ahead of time. As graduate students, you are expected to be able to do some research and self-teaching on your own to build your coding skills, and of course you can *always* come ask me for help!" ] }, { "cell_type": "markdown", "id": "hourly-patch", "metadata": {}, "source": [ "A nice reference for a lot of the computational skills we'll be covering (coding, unix command line, git) is the \"Software Carpentry\" set of lessons: https://software-carpentry.org/lessons/. You should seriously considering checking their tutorials for extra practice and more in-depth lessons!" ] }, { "cell_type": "markdown", "id": "f162de59", "metadata": {}, "source": [ "This document is a \"Jupyter Notebook\". It's kind of like interactive mode, but also lets you intersperse text, html, etc, among it. (It's free and easy to set up.)" ] }, { "cell_type": "markdown", "id": "tough-fleece", "metadata": {}, "source": [ "
" ] }, { "cell_type": "markdown", "id": "entertaining-wallace", "metadata": {}, "source": [ "Python is a **whitespace-based language**. In C, C++, Java, and many other languages, you use braces to group code:\n", "```java\n", "if (x == 1) {\n", " do_something();\n", "}\n", "```\n", "and the spacing is just for readability. For example, the following code does the same thing:\n", "```java\n", "if (x == 1) { do_something();\n", " }\n", "```\n", "\n", "In Python you use indenting, and colons (`:`) to have the same effect. You also do not use semicolons (`;`) to end commands.\n", "```py\n", "if x == 1:\n", " do_something()\n", "```" ] }, { "cell_type": "markdown", "id": "narrative-turtle", "metadata": {}, "source": [ "
" ] }, { "cell_type": "markdown", "id": "desperate-stream", "metadata": {}, "source": [ "You have to be *really* careful to be consistent by either\n", "- always using tabs, or\n", "- always using spaces (and the same number)" ] }, { "cell_type": "code", "execution_count": null, "id": "noted-staff", "metadata": {}, "outputs": [], "source": [ "x = 1" ] }, { "cell_type": "code", "execution_count": null, "id": "clear-spank", "metadata": {}, "outputs": [], "source": [ "if x == 1:\n", " print(\"hello\")" ] }, { "cell_type": "code", "execution_count": null, "id": "synthetic-filter", "metadata": {}, "outputs": [], "source": [ "if x == 1:\n", " print(\"hello\")" ] }, { "cell_type": "code", "execution_count": null, "id": "broke-responsibility", "metadata": {}, "outputs": [], "source": [ "if x == 1:\n", " print(\"hello\")\n", " print(\"world\")" ] }, { "cell_type": "code", "execution_count": null, "id": "sixth-bearing", "metadata": {}, "outputs": [], "source": [ "if x == 1:\n", " print(\"hello\")\n", " print(\"world\") # if you use a tab, Jupyter will fix it for you automatically! Your code editor might not." ] }, { "cell_type": "markdown", "id": "union-nursery", "metadata": {}, "source": [ "
" ] }, { "cell_type": "markdown", "id": "catholic-weapon", "metadata": {}, "source": [ "Python uses `if`, `for`, and `while` statements like many other languages." ] }, { "cell_type": "code", "execution_count": null, "id": "legal-microphone", "metadata": {}, "outputs": [], "source": [ "x = 1\n", "while x < 10:\n", " x = x + 2\n", " \n", " print(x)" ] }, { "cell_type": "code", "execution_count": null, "id": "central-authority", "metadata": {}, "outputs": [], "source": [ "for y in range(3, 6): # 3, 4, 5\n", " print(y)" ] }, { "cell_type": "code", "execution_count": null, "id": "variable-founder", "metadata": {}, "outputs": [], "source": [ "for letter in \"apple\":\n", " print(letter)" ] }, { "cell_type": "markdown", "id": "professional-colleague", "metadata": {}, "source": [ "In a `for` loop, you can iterate over many different types of objects (lists, sets, tuples, dictionaries, strings, etc.)" ] }, { "cell_type": "markdown", "id": "macro-groove", "metadata": {}, "source": [ "`range(a,b)` is a way of looping over all of the integers between `a` (inclusive) and `b` (exclusive). " ] }, { "cell_type": "code", "execution_count": null, "id": "white-decision", "metadata": {}, "outputs": [], "source": [ "for z in \"hello\":\n", " print(z)" ] }, { "cell_type": "code", "execution_count": null, "id": "medieval-entry", "metadata": {}, "outputs": [], "source": [ "for z in [19, -100, \"banana\"]:\n", " print(z+1)" ] }, { "cell_type": "markdown", "id": "lasting-birth", "metadata": {}, "source": [ "
" ] }, { "cell_type": "markdown", "id": "textile-delight", "metadata": {}, "source": [ "You may have noticed that Python is not a **statically-typed** language, which means you do not need to tell it whether a variable you are defining is an integer or a string or a list, etc. You just define it, and it figures it out." ] }, { "cell_type": "markdown", "id": "voluntary-pollution", "metadata": {}, "source": [ "But, there are still different types! You can always use the `type` function to check what type an object has." ] }, { "cell_type": "code", "execution_count": null, "id": "blank-chrome", "metadata": {}, "outputs": [], "source": [ "L = [1, 2, 3]\n", "type(L)" ] }, { "cell_type": "code", "execution_count": null, "id": "awful-chapel", "metadata": {}, "outputs": [], "source": [ "L = (1,2,3)\n", "type(L)" ] }, { "cell_type": "code", "execution_count": null, "id": "announced-prisoner", "metadata": {}, "outputs": [], "source": [ "L = {1,2,3}\n", "type(L)" ] }, { "cell_type": "code", "execution_count": null, "id": "outstanding-malaysia", "metadata": {}, "outputs": [], "source": [ "sum([1,2,3])" ] }, { "cell_type": "code", "execution_count": null, "id": "blind-christopher", "metadata": {}, "outputs": [], "source": [ "type(sum)" ] }, { "cell_type": "markdown", "id": "egyptian-kazakhstan", "metadata": {}, "source": [ "Now we're going to discuss a bunch of the fundamental types in Python." ] }, { "cell_type": "markdown", "id": "classified-style", "metadata": {}, "source": [ "## Integers, Floating Point Numbers, and Complex Numbers" ] }, { "cell_type": "code", "execution_count": null, "id": "wired-truck", "metadata": {}, "outputs": [], "source": [ "x = 7\n", "type(x)" ] }, { "cell_type": "code", "execution_count": null, "id": "explicit-hostel", "metadata": {}, "outputs": [], "source": [ "import math\n", "math.pi" ] }, { "cell_type": "code", "execution_count": null, "id": "elementary-sugar", "metadata": {}, "outputs": [], "source": [ "x = 7.0\n", "type(x)" ] }, { "cell_type": "code", "execution_count": null, "id": "persistent-nightlife", "metadata": {}, "outputs": [], "source": [ "x = 3.0000000000000000001\n", "print(x)" ] }, { "cell_type": "code", "execution_count": null, "id": "bigger-degree", "metadata": {}, "outputs": [], "source": [ "y = 0.1\n", "print(y)" ] }, { "cell_type": "code", "execution_count": null, "id": "functioning-jerusalem", "metadata": {}, "outputs": [], "source": [ "0.1 + 0.1 + 0.1 - 0.3" ] }, { "cell_type": "code", "execution_count": null, "id": "faced-enlargement", "metadata": {}, "outputs": [], "source": [ "0.1 + 0.1 + 0.1 == 0.3" ] }, { "cell_type": "code", "execution_count": null, "id": "assumed-intention", "metadata": {}, "outputs": [], "source": [ "15 / 7" ] }, { "cell_type": "code", "execution_count": null, "id": "authentic-romantic", "metadata": {}, "outputs": [], "source": [ "15 // 7 " ] }, { "cell_type": "code", "execution_count": null, "id": "desirable-exhaust", "metadata": {}, "outputs": [], "source": [ "z = complex(3, 5)\n", "t = complex(1,-1)\n", "print(z)\n", "type(z)\n", "z*t" ] }, { "cell_type": "markdown", "id": "short-timothy", "metadata": {}, "source": [ "## Boolean" ] }, { "cell_type": "markdown", "id": "unable-candidate", "metadata": {}, "source": [ "A boolean is just a `True` or `False` value. That's it!" ] }, { "cell_type": "code", "execution_count": null, "id": "plain-cherry", "metadata": {}, "outputs": [], "source": [ "b = True\n", "type(b)" ] }, { "cell_type": "code", "execution_count": null, "id": "criminal-harrison", "metadata": {}, "outputs": [], "source": [ "if b:\n", " print(\"hello\")" ] }, { "cell_type": "code", "execution_count": null, "id": "significant-completion", "metadata": {}, "outputs": [], "source": [ "if not b:\n", " print(\"hello\")" ] }, { "cell_type": "code", "execution_count": null, "id": "hourly-wildlife", "metadata": {}, "outputs": [], "source": [ "t = 10 + 10 == 20 # Use \"==\" to test equality, and \"=\" to actually set something equal\n", "print(t)\n", "type(t)" ] }, { "cell_type": "markdown", "id": "asian-rally", "metadata": {}, "source": [ "## None" ] }, { "cell_type": "markdown", "id": "typical-catering", "metadata": {}, "source": [ "There is a weird object in Python called `None`. It's just a useful thing to have around, often as a default value until you assign something." ] }, { "cell_type": "code", "execution_count": null, "id": "pointed-resource", "metadata": {}, "outputs": [], "source": [ "y = None\n", "print(y)\n", "if y is None:\n", " print(\"y has the value None\")\n", "y = 3\n", "if y is None:\n", " print(\"y has the value None\")" ] }, { "cell_type": "markdown", "id": "bizarre-belle", "metadata": {}, "source": [ "## Strings" ] }, { "cell_type": "markdown", "id": "nuclear-vermont", "metadata": {}, "source": [ "A string is just a sequence of characters." ] }, { "cell_type": "code", "execution_count": null, "id": "compatible-swiss", "metadata": {}, "outputs": [], "source": [ "type(\"banana\")\n", "'banana'" ] }, { "cell_type": "markdown", "id": "activated-regression", "metadata": {}, "source": [ "You can do a million things with strings." ] }, { "cell_type": "code", "execution_count": null, "id": "distinct-measure", "metadata": {}, "outputs": [], "source": [ "s = \"banana\"\n", "s.split(\"n\")" ] }, { "cell_type": "markdown", "id": "selective-transfer", "metadata": {}, "source": [ "Use `len` to find the length of a string and `+` to concatenate two strings together." ] }, { "cell_type": "code", "execution_count": null, "id": "republican-dryer", "metadata": {}, "outputs": [], "source": [ "one = \"hello\"\n", "two = \"world\"\n", "three = one + \" \" + two\n", "print(len(three))\n", "print(three)" ] }, { "cell_type": "code", "execution_count": null, "id": "shared-defensive", "metadata": {}, "outputs": [], "source": [ "three.len()" ] }, { "cell_type": "markdown", "id": "technological-prayer", "metadata": {}, "source": [ "## Lists\n", "A list is an **ordered sequence** of things." ] }, { "cell_type": "code", "execution_count": null, "id": "biological-genius", "metadata": {}, "outputs": [], "source": [ "L = [15, \"banana\", 7, False, [1, 2, 3]]" ] }, { "cell_type": "code", "execution_count": null, "id": "improving-exhibit", "metadata": {}, "outputs": [], "source": [ "print(L)" ] }, { "cell_type": "markdown", "id": "renewable-prescription", "metadata": {}, "source": [ "Elements of lists are accessed with bracket notation, starting from 0." ] }, { "cell_type": "code", "execution_count": null, "id": "future-operator", "metadata": {}, "outputs": [], "source": [ "L[0]" ] }, { "cell_type": "code", "execution_count": null, "id": "local-cradle", "metadata": {}, "outputs": [], "source": [ "L[1]" ] }, { "cell_type": "code", "execution_count": null, "id": "approved-boxing", "metadata": {}, "outputs": [], "source": [ "L[2]" ] }, { "cell_type": "code", "execution_count": null, "id": "single-bermuda", "metadata": {}, "outputs": [], "source": [ "L[3]" ] }, { "cell_type": "code", "execution_count": null, "id": "advance-organization", "metadata": {}, "outputs": [], "source": [ "L[4]" ] }, { "cell_type": "code", "execution_count": null, "id": "violent-headquarters", "metadata": {}, "outputs": [], "source": [ "(L[4])[1]" ] }, { "cell_type": "markdown", "id": "stupid-examination", "metadata": {}, "source": [ "Use `len(L)` to get the length of a list." ] }, { "cell_type": "code", "execution_count": null, "id": "moderate-london", "metadata": {}, "outputs": [], "source": [ "len(L)" ] }, { "cell_type": "code", "execution_count": null, "id": "living-aurora", "metadata": {}, "outputs": [], "source": [ "len(L[4])" ] }, { "cell_type": "markdown", "id": "coupled-tattoo", "metadata": {}, "source": [ "You can set elements of the list manually as well." ] }, { "cell_type": "code", "execution_count": null, "id": "intermediate-texas", "metadata": {}, "outputs": [], "source": [ "L" ] }, { "cell_type": "code", "execution_count": null, "id": "designed-tobago", "metadata": {}, "outputs": [], "source": [ "L[1] = \"apple\"" ] }, { "cell_type": "code", "execution_count": null, "id": "incident-contribution", "metadata": {}, "outputs": [], "source": [ "L" ] }, { "cell_type": "code", "execution_count": null, "id": "buried-jimmy", "metadata": {}, "outputs": [], "source": [ "L[8] = \"can't set this\"" ] }, { "cell_type": "markdown", "id": "pacific-sheep", "metadata": {}, "source": [ "You can sort lists:" ] }, { "cell_type": "code", "execution_count": null, "id": "statistical-millennium", "metadata": {}, "outputs": [], "source": [ "R = [15, -20, 0]\n", "R.sort()\n", "print(R)" ] }, { "cell_type": "markdown", "id": "collective-alliance", "metadata": {}, "source": [ "Notice the `.` in the notation above. We'll talk about this more when we cover object-oriented programming, but what we're basically doing here is telling the list `R` to perform its `sort()` operation on itself." ] }, { "cell_type": "markdown", "id": "partial-realtor", "metadata": {}, "source": [ "You may wonder why we did `len(R)` instead of `R.len()`... it's kind of just a quirk. You get used to it." ] }, { "cell_type": "markdown", "id": "clear-aaron", "metadata": {}, "source": [ "A few more quick list functions:" ] }, { "cell_type": "code", "execution_count": null, "id": "medical-academy", "metadata": {}, "outputs": [], "source": [ "R" ] }, { "cell_type": "code", "execution_count": null, "id": "strong-algorithm", "metadata": {}, "outputs": [], "source": [ "R.append(17)\n", "print(R)" ] }, { "cell_type": "code", "execution_count": null, "id": "transsexual-writer", "metadata": {}, "outputs": [], "source": [ "R.extend([7, 8, 9])\n", "print(R)" ] }, { "cell_type": "markdown", "id": "statutory-solid", "metadata": {}, "source": [ "Lastly (for now) you can concatenate two lists together with the `+` sign." ] }, { "cell_type": "code", "execution_count": null, "id": "indonesian-possession", "metadata": {}, "outputs": [], "source": [ "[1,2,3] + [4,5,6]" ] }, { "cell_type": "code", "execution_count": null, "id": "capable-collect", "metadata": {}, "outputs": [], "source": [ "print(R)\n", "M = [100] + R\n", "print(M)" ] }, { "cell_type": "markdown", "id": "necessary-ethernet", "metadata": {}, "source": [ "## Sets" ] }, { "cell_type": "markdown", "id": "hidden-elements", "metadata": {}, "source": [ "A list was an ordered sequence of things. A set is an **unordered sequence** of things with no repeats (just like in math)." ] }, { "cell_type": "code", "execution_count": null, "id": "seeing-dairy", "metadata": {}, "outputs": [], "source": [ "S = {1, 2, 3, 4}\n", "print(S)" ] }, { "cell_type": "code", "execution_count": null, "id": "conventional-binding", "metadata": {}, "outputs": [], "source": [ "T = {3, 1, 4, 2}\n", "print(T)" ] }, { "cell_type": "code", "execution_count": null, "id": "educated-verification", "metadata": {}, "outputs": [], "source": [ "S == T" ] }, { "cell_type": "markdown", "id": "dress-simulation", "metadata": {}, "source": [ "You can't access elements using the bracket notation because there is no first element, second element, etc. You should never assume that you know the order Python will internally store your list in!" ] }, { "cell_type": "code", "execution_count": null, "id": "related-basis", "metadata": {}, "outputs": [], "source": [ "S[2]" ] }, { "cell_type": "code", "execution_count": null, "id": "egyptian-zambia", "metadata": {}, "outputs": [], "source": [ "for element in S:\n", " print(element)" ] }, { "cell_type": "raw", "id": "severe-geometry", "metadata": {}, "source": [ "Here are some functions you can do with sets:" ] }, { "cell_type": "code", "execution_count": null, "id": "chief-academy", "metadata": {}, "outputs": [], "source": [ "first = {1,5,6}\n", "second = {2,4,5}" ] }, { "cell_type": "code", "execution_count": null, "id": "copyrighted-physiology", "metadata": {}, "outputs": [], "source": [ "first.union(second)" ] }, { "cell_type": "code", "execution_count": null, "id": "direct-veteran", "metadata": {}, "outputs": [], "source": [ "second.union(first)" ] }, { "cell_type": "code", "execution_count": null, "id": "played-induction", "metadata": {}, "outputs": [], "source": [ "first.intersection(second)" ] }, { "cell_type": "code", "execution_count": null, "id": "major-percentage", "metadata": {}, "outputs": [], "source": [ "first.difference(second) # all of the things IN first, and NOT IN second" ] }, { "cell_type": "code", "execution_count": null, "id": "critical-martial", "metadata": {}, "outputs": [], "source": [ "# By the way, you write comments in python by just starting the line with the pound key." ] }, { "cell_type": "code", "execution_count": null, "id": "executive-hudson", "metadata": {}, "outputs": [], "source": [ "first" ] }, { "cell_type": "code", "execution_count": null, "id": "detailed-topic", "metadata": {}, "outputs": [], "source": [ "first.add(9)\n", "print(first)" ] }, { "cell_type": "code", "execution_count": null, "id": "infrared-vulnerability", "metadata": {}, "outputs": [], "source": [ "first.add(5)\n", "print(first) # No duplicates!" ] }, { "cell_type": "code", "execution_count": null, "id": "seventh-hotel", "metadata": {}, "outputs": [], "source": [ "first.remove(5)" ] }, { "cell_type": "code", "execution_count": null, "id": "duplicate-summit", "metadata": {}, "outputs": [], "source": [ "print(first)" ] }, { "cell_type": "code", "execution_count": null, "id": "periodic-strand", "metadata": {}, "outputs": [], "source": [ "first.remove(5)" ] }, { "cell_type": "markdown", "id": "falling-convenience", "metadata": {}, "source": [ "## Tuples" ] }, { "cell_type": "markdown", "id": "parallel-appearance", "metadata": {}, "source": [ "It starts to get a little tricky here! A tuple is an **ordered sequence** of things." ] }, { "cell_type": "markdown", "id": "identical-synthetic", "metadata": {}, "source": [ "Wait... isn't that what a list was?" ] }, { "cell_type": "code", "execution_count": null, "id": "described-warning", "metadata": {}, "outputs": [], "source": [ "T = (1,2,3,4)\n", "print(T)\n", "type(T)" ] }, { "cell_type": "code", "execution_count": null, "id": "massive-piece", "metadata": {}, "outputs": [], "source": [ "L = [1,2,3,4]\n", "L == T # They are different types of objects, so they can't be equal." ] }, { "cell_type": "markdown", "id": "funded-language", "metadata": {}, "source": [ "The key is that a tuple is what we call **immutable**. Once it's defined, it *cannot* be changed, ever, at all." ] }, { "cell_type": "code", "execution_count": null, "id": "noble-grill", "metadata": {}, "outputs": [], "source": [ "print(T)\n", "print(T[2])" ] }, { "cell_type": "code", "execution_count": null, "id": "willing-merchant", "metadata": {}, "outputs": [], "source": [ "T[2] = 17" ] }, { "cell_type": "markdown", "id": "vital-aquarium", "metadata": {}, "source": [ "It is still possible to do things like concatenate two tuples to make a new bigger tuple, but it's a **new** bigger tuple, and the original one is still unchanged." ] }, { "cell_type": "code", "execution_count": null, "id": "involved-munich", "metadata": {}, "outputs": [], "source": [ "T + (5,6)" ] }, { "cell_type": "code", "execution_count": null, "id": "temporal-hours", "metadata": {}, "outputs": [], "source": [ "T" ] }, { "cell_type": "code", "execution_count": null, "id": "junior-appliance", "metadata": {}, "outputs": [], "source": [ "T.append(5)" ] }, { "cell_type": "markdown", "id": "fundamental-factor", "metadata": {}, "source": [ "So, we define a new tuple with parentheses, but there's one catch: if your tuple has a single item, it needs a special bit of syntax." ] }, { "cell_type": "code", "execution_count": null, "id": "cosmetic-raleigh", "metadata": {}, "outputs": [], "source": [ "x = (1)\n", "print(x)\n", "type(x)" ] }, { "cell_type": "code", "execution_count": null, "id": "recorded-canadian", "metadata": {}, "outputs": [], "source": [ "x = (1,)\n", "print(x)\n", "type(x)" ] }, { "cell_type": "markdown", "id": "military-browser", "metadata": {}, "source": [ "So, lists are **mutable**, tuples are **immutable**. Why do we need two different versions?" ] }, { "cell_type": "code", "execution_count": null, "id": "cooperative-muscle", "metadata": {}, "outputs": [], "source": [ "L = [1,2,3,4,5,6]\n", "5 in L" ] }, { "cell_type": "markdown", "id": "perceived-morrison", "metadata": {}, "source": [ "Under-the-hood, when you store things in a set, Python is being super smart about how it stores it. When you add an element to a set you really do not want python to have to scan one-by-one through all the things in the set to make sure it's not already there. So, it uses a clever technique called *hashing*." ] }, { "cell_type": "markdown", "id": "imported-upper", "metadata": {}, "source": [ "You don't need to know the details right now, but the broad idea is that Python takes each thing in the set and assigns a number to it called its *hash*, and then uses the hashes to make sure there are no duplicates." ] }, { "cell_type": "code", "execution_count": null, "id": "insured-nepal", "metadata": {}, "outputs": [], "source": [ "hash(17)" ] }, { "cell_type": "code", "execution_count": null, "id": "guilty-granny", "metadata": {}, "outputs": [], "source": [ "hash(\"banana\")" ] }, { "cell_type": "code", "execution_count": null, "id": "vocational-accreditation", "metadata": {}, "outputs": [], "source": [ "hash((1,2,3,4))" ] }, { "cell_type": "code", "execution_count": null, "id": "recorded-intellectual", "metadata": {}, "outputs": [], "source": [ "hash([1,2,3])" ] }, { "cell_type": "code", "execution_count": null, "id": "brutal-popularity", "metadata": {}, "outputs": [], "source": [ "L = [1,2,3,4]" ] }, { "cell_type": "code", "execution_count": null, "id": "developing-strike", "metadata": {}, "outputs": [], "source": [ "{[1, 2, 3, 4], [1, 2], [7,8]}" ] }, { "cell_type": "code", "execution_count": null, "id": "enclosed-mixer", "metadata": {}, "outputs": [], "source": [ "{(1, 2, 3, 4), (1, 2), (7, 8)}" ] }, { "cell_type": "markdown", "id": "mysterious-orchestra", "metadata": {}, "source": [ "The problem is that you **can't hash mutable things**. Once you get an object's hash, that needs to stay its hash forever. You could hash a list, then appending an element to the list would mean a new hash would have to be generated, and this would mess everything up." ] }, { "cell_type": "markdown", "id": "liquid-bundle", "metadata": {}, "source": [ "Bottom line: Sometimes you need an immutable version of something, like to put it in a set." ] }, { "cell_type": "code", "execution_count": null, "id": "several-joshua", "metadata": {}, "outputs": [], "source": [ "{5, 17, [1,2,3]}" ] }, { "cell_type": "code", "execution_count": null, "id": "mexican-blackberry", "metadata": {}, "outputs": [], "source": [ "{5, 17, (1,2,3)}" ] }, { "cell_type": "code", "execution_count": null, "id": "divine-taiwan", "metadata": {}, "outputs": [], "source": [ "{5, 17, {1,2,3}}" ] }, { "cell_type": "markdown", "id": "wound-bulgaria", "metadata": {}, "source": [ "Sets are mutable too! Sets must contain immutable things, but they themselves are mutable.\n", "\n", "Of course we knew this, because we can do `S.add()`. So what if you want sets in your sets? There is an immutable version of a set called a `frozenset`." ] }, { "cell_type": "code", "execution_count": null, "id": "thorough-microphone", "metadata": {}, "outputs": [], "source": [ "{ 5, 17, frozenset({1, 2, 3}) }" ] }, { "cell_type": "markdown", "id": "athletic-mixer", "metadata": {}, "source": [ "When should you use a tuple versus a list?\n", "- If it's going to go in a set (or, as we'll see in a second, in a dictionary), it has to be immutable. Thus, use a tuple.\n", "- If you need to be able to add and remove things, use a list.\n", "- If the size will always stay the same, you probably want a tuple. For example, if you're representing xy-coordiates, use tuples." ] }, { "cell_type": "markdown", "id": "brave-employer", "metadata": {}, "source": [ "## Dictionaries" ] }, { "cell_type": "markdown", "id": "distributed-trace", "metadata": {}, "source": [ "You can think of a list as kind of like a mathematical function whose inputs are the the indices 0, 1, ... and whose outputs are the elements of the list." ] }, { "cell_type": "code", "execution_count": null, "id": "varied-contest", "metadata": {}, "outputs": [], "source": [ "L = [\"apple\", \"banana\", \"pear\"]" ] }, { "cell_type": "code", "execution_count": null, "id": "legitimate-prison", "metadata": {}, "outputs": [], "source": [ "# 0 -> apple, 1 -> banana, 2 -> pear" ] }, { "cell_type": "markdown", "id": "unavailable-manchester", "metadata": {}, "source": [ "In a dictionary, the inputs don't have to be integers, they can be any (immutable) object." ] }, { "cell_type": "code", "execution_count": null, "id": "generic-power", "metadata": {}, "outputs": [], "source": [ "# To define 17 -> apple, banana -> pear, (1, 2, 3) -> True\n", "d = {17:\"apple\", \"banana\":\"pear\", (1,2,3):True}\n", "print(d)" ] }, { "cell_type": "markdown", "id": "micro-revelation", "metadata": {}, "source": [ "The inputs are called **keys** and the outputs are called **values**." ] }, { "cell_type": "code", "execution_count": null, "id": "official-saturday", "metadata": {}, "outputs": [], "source": [ "d[17]" ] }, { "cell_type": "code", "execution_count": null, "id": "broad-cookbook", "metadata": {}, "outputs": [], "source": [ "d[\"banana\"]" ] }, { "cell_type": "code", "execution_count": null, "id": "temporal-exclusion", "metadata": {}, "outputs": [], "source": [ "d[(1,2,3)]" ] }, { "cell_type": "code", "execution_count": null, "id": "available-contrary", "metadata": {}, "outputs": [], "source": [ "d[\"pear\"] = \"hello\"\n", "d[\"pear\"]" ] }, { "cell_type": "markdown", "id": "large-prerequisite", "metadata": {}, "source": [ "You can assign new values too" ] }, { "cell_type": "code", "execution_count": null, "id": "retained-fortune", "metadata": {}, "outputs": [], "source": [ "d[1] = \"one\"\n", "print(d)" ] }, { "cell_type": "code", "execution_count": null, "id": "responsible-knife", "metadata": {}, "outputs": [], "source": [ "d[ (2, 3, 5, 7) ] = False" ] }, { "cell_type": "markdown", "id": "vulnerable-black", "metadata": {}, "source": [ "Dictionaries are *super* useful, but take some getting used to. The keys are hashed in the background, which makes looking up the value for a given key very fast." ] }, { "cell_type": "code", "execution_count": null, "id": "available-element", "metadata": {}, "outputs": [], "source": [ "for k in d.keys():\n", " print(k)" ] }, { "cell_type": "code", "execution_count": null, "id": "increased-functionality", "metadata": {}, "outputs": [], "source": [ "for v in d.values():\n", " print(v)" ] }, { "cell_type": "code", "execution_count": null, "id": "preceding-sight", "metadata": {}, "outputs": [], "source": [ "for pair in d.items():\n", " print(pair)\n", "# (key, value)" ] }, { "cell_type": "markdown", "id": "ready-story", "metadata": {}, "source": [ "## Casting" ] }, { "cell_type": "markdown", "id": "frozen-sauce", "metadata": {}, "source": [ "You can tell Python to turn an object of one type into an object of another type. This is called **casting**." ] }, { "cell_type": "code", "execution_count": null, "id": "lovely-terrain", "metadata": {}, "outputs": [], "source": [ "L = [3, 7, 7, 12]\n", "print(L)" ] }, { "cell_type": "code", "execution_count": null, "id": "exposed-development", "metadata": {}, "outputs": [], "source": [ "T = tuple(L)\n", "print(T)\n", "print(L)" ] }, { "cell_type": "code", "execution_count": null, "id": "flush-cause", "metadata": {}, "outputs": [], "source": [ "S = set(L)\n", "print(S)" ] }, { "cell_type": "code", "execution_count": null, "id": "precise-chile", "metadata": {}, "outputs": [], "source": [ "print(L)\n", "list(set(L))" ] }, { "cell_type": "code", "execution_count": null, "id": "instrumental-tracy", "metadata": {}, "outputs": [], "source": [ "dict(L)" ] }, { "cell_type": "code", "execution_count": null, "id": "reserved-hunter", "metadata": {}, "outputs": [], "source": [ "str(L)" ] }, { "cell_type": "code", "execution_count": null, "id": "experimental-defeat", "metadata": {}, "outputs": [], "source": [ "int(L)" ] }, { "cell_type": "code", "execution_count": null, "id": "dangerous-password", "metadata": {}, "outputs": [], "source": [ "d = {1:\"one\", 2:\"two\", 3:\"three\"}" ] }, { "cell_type": "code", "execution_count": null, "id": "inside-collective", "metadata": {}, "outputs": [], "source": [ "list(d)" ] }, { "cell_type": "markdown", "id": "vertical-pulse", "metadata": {}, "source": [ "
" ] }, { "cell_type": "markdown", "id": "duplicate-homework", "metadata": {}, "source": [ "Time for some practice!" ] }, { "cell_type": "markdown", "id": "metric-notebook", "metadata": {}, "source": [ "https://projecteuler.net/" ] }, { "cell_type": "markdown", "id": "refined-missouri", "metadata": {}, "source": [ "Problem 1: mod, looping, and comprehensions" ] }, { "cell_type": "markdown", "id": "global-commercial", "metadata": {}, "source": [ "Problem 2: negative indexing" ] }, { "cell_type": "markdown", "id": "allied-entertainment", "metadata": {}, "source": [ "Problem 5: all / any, and thinking mathematically" ] }, { "cell_type": "markdown", "id": "tracked-married", "metadata": {}, "source": [ "
" ] }, { "cell_type": "markdown", "id": "iraqi-delta", "metadata": {}, "source": [ "If we list all the natural numbers below 10 that are multiples of 3 or 5, we get 3, 5, 6 and 9. The sum of these multiples is 23.\n", "\n", "Find the sum of all the multiples of 3 or 5 below 1000." ] }, { "cell_type": "code", "execution_count": null, "id": "imperial-medline", "metadata": {}, "outputs": [], "source": [ "# mod - modulus\n", "# a % b -- the remainder you get when you divide a by b\n", "\n", "# list comprehensions\n", "# += " ] }, { "cell_type": "code", "execution_count": null, "id": "eligible-salmon", "metadata": {}, "outputs": [], "source": [] }, { "cell_type": "markdown", "id": "english-means", "metadata": {}, "source": [ "Each new term in the Fibonacci sequence is generated by adding the previous two terms. By starting with 1 and 2, the first 10 terms will be:\n", "\n", "1, 2, 3, 5, 8, 13, 21, 34, 55, 89, ...\n", "\n", "By considering the terms in the Fibonacci sequence whose values do not exceed four million, find the sum of the even-valued terms." ] }, { "cell_type": "code", "execution_count": null, "id": "according-equipment", "metadata": {}, "outputs": [], "source": [] }, { "cell_type": "markdown", "id": "comic-vietnam", "metadata": {}, "source": [ "2520 is the smallest number that can be divided by each of the numbers from 1 to 10 without any remainder.\n", "\n", "What is the smallest positive number that is evenly divisible by all of the numbers from 1 to 20?" ] }, { "cell_type": "code", "execution_count": null, "id": "civil-sterling", "metadata": {}, "outputs": [], "source": [ "# all / any" ] }, { "cell_type": "code", "execution_count": null, "id": "optional-detail", "metadata": {}, "outputs": [], "source": [] } ], "metadata": { "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.1" } }, "nbformat": 4, "nbformat_minor": 5 }